Fix incosistencies in the custom commission types
This commit is contained in:
@ -42,28 +42,33 @@ export default async function CommissionsPage() {
|
|||||||
<div className="mx-auto w-full max-w-6xl px-4 py-8 flex flex-col gap-8">
|
<div className="mx-auto w-full max-w-6xl px-4 py-8 flex flex-col gap-8">
|
||||||
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<h1 className="text-3xl font-bold">Commission Pricing</h1>
|
<h1 className="text-3xl font-bold">Commission Pricing</h1>
|
||||||
{guidelines?.exampleImageUrl ? (
|
<div className="flex flex-wrap gap-3">
|
||||||
<Dialog>
|
<Button asChild>
|
||||||
<DialogTrigger asChild>
|
<a href="#commission-request-form">Get to the request form</a>
|
||||||
<Button variant="secondary">View example</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
{guidelines?.exampleImageUrl ? (
|
||||||
<DialogContent className="flex w-auto! max-w-[95vw]! flex-col p-4 sm:p-6">
|
<Dialog>
|
||||||
<DialogHeader className="sr-only">
|
<DialogTrigger asChild>
|
||||||
<DialogTitle>Commission example</DialogTitle>
|
<Button variant="secondary">View example</Button>
|
||||||
</DialogHeader>
|
</DialogTrigger>
|
||||||
<div className="flex max-h-[85vh] max-w-[85vw] items-center justify-center rounded-xl border-border/60 bg-muted p-2 shadow-2xl">
|
<DialogContent className="flex w-auto! max-w-[95vw]! flex-col p-4 sm:p-6">
|
||||||
<Image
|
<DialogHeader className="sr-only">
|
||||||
src={guidelines.exampleImageUrl}
|
<DialogTitle>Commission example</DialogTitle>
|
||||||
alt="Commission example"
|
</DialogHeader>
|
||||||
width={1600}
|
<div className="flex max-h-[85vh] max-w-[85vw] items-center justify-center rounded-xl border-border/60 bg-muted p-2 shadow-2xl">
|
||||||
height={1200}
|
<Image
|
||||||
sizes="85vw"
|
src={guidelines.exampleImageUrl}
|
||||||
className="h-auto max-h-[85vh] w-auto max-w-[85vw] rounded-lg object-contain"
|
alt="Commission example"
|
||||||
/>
|
width={1600}
|
||||||
</div>
|
height={1200}
|
||||||
</DialogContent>
|
sizes="85vw"
|
||||||
</Dialog>
|
className="h-auto max-h-[85vh] w-auto max-w-[85vw] rounded-lg object-contain"
|
||||||
) : null}
|
/>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 items-start">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 items-start">
|
||||||
{commissions.map((commission) => (
|
{commissions.map((commission) => (
|
||||||
@ -75,7 +80,9 @@ export default async function CommissionsPage() {
|
|||||||
<CommissionGuidelines />
|
<CommissionGuidelines />
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<h2 className="text-2xl font-semibold">Request a Commission</h2>
|
<h2 id="commission-request-form" className="text-2xl font-semibold scroll-mt-24">
|
||||||
|
Request a Commission
|
||||||
|
</h2>
|
||||||
<CommissionOrderForm types={commissions} customCards={customCards} />
|
<CommissionOrderForm types={commissions} customCards={customCards} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
type CustomCardOption = {
|
type CustomCardOption = {
|
||||||
@ -43,98 +44,107 @@ export function CommissionCustomCard({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full">
|
<div className="flex flex-col h-full">
|
||||||
<Card className="flex flex-col flex-1 relative overflow-hidden border-2 border-primary/50 shadow-sm">
|
<div className="overflow-hidden h-full">
|
||||||
{card.isSpecialOffer ? (
|
<Card
|
||||||
<div className="pointer-events-none absolute right-0 top-0 z-10">
|
className={cn(
|
||||||
<div className="absolute right-0 top-16 h-7 w-36 origin-top-right translate-x-10 rotate-45 bg-primary text-primary-foreground shadow-md">
|
"flex flex-col h-full relative shadow-sm",
|
||||||
<span className="flex h-full w-full items-center justify-center text-xs font-semibold uppercase tracking-wide">
|
card.isSpecialOffer
|
||||||
Special
|
? "border-2 border-primary/50"
|
||||||
</span>
|
: "border-border"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{card.isSpecialOffer ? (
|
||||||
|
<div className="pointer-events-none absolute right-0 top-0 z-10 overflow-visible">
|
||||||
|
<div className="absolute right-0 top-16 h-7 w-36 origin-top-right translate-x-10 rotate-45 bg-primary text-primary-foreground shadow-md">
|
||||||
|
<span className="flex h-full w-full items-center justify-center text-xs font-semibold uppercase tracking-wide">
|
||||||
|
Special
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
<CardHeader className="gap-2">
|
|
||||||
<CardTitle className="text-xl font-bold">{card.name}</CardTitle>
|
|
||||||
<p className="text-muted-foreground text-sm">{card.description}</p>
|
|
||||||
{card.referenceImageUrl ? (
|
|
||||||
<Dialog>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="group relative overflow-hidden rounded-lg border border-border/60 bg-muted/40"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
src={card.referenceImageUrl}
|
|
||||||
alt={`${card.name} reference`}
|
|
||||||
width={800}
|
|
||||||
height={600}
|
|
||||||
sizes="(max-width: 768px) 90vw, 400px"
|
|
||||||
className="h-auto w-full object-cover transition-transform duration-200 group-hover:scale-[1.02]"
|
|
||||||
/>
|
|
||||||
<span className="absolute inset-x-0 bottom-0 bg-background/70 px-2 py-1 text-xs text-foreground/80">
|
|
||||||
Click to enlarge
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent className="flex w-auto! max-w-[95vw]! flex-col p-4 sm:p-6">
|
|
||||||
<DialogHeader className="sr-only">
|
|
||||||
<DialogTitle>{card.name} reference</DialogTitle>
|
|
||||||
</DialogHeader>
|
|
||||||
<div className="flex max-h-[85vh] max-w-[85vw] items-center justify-center rounded-xl border-border/60 bg-muted p-2 shadow-2xl">
|
|
||||||
<Image
|
|
||||||
src={card.referenceImageUrl}
|
|
||||||
alt={`${card.name} reference`}
|
|
||||||
width={1600}
|
|
||||||
height={1200}
|
|
||||||
sizes="85vw"
|
|
||||||
className="h-auto max-h-[85vh] w-auto max-w-[85vw] rounded-lg object-contain"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
) : null}
|
) : null}
|
||||||
</CardHeader>
|
<CardHeader className="gap-2">
|
||||||
|
<CardTitle className="text-xl font-bold">{card.name}</CardTitle>
|
||||||
<CardContent className="flex flex-col justify-start gap-4">
|
<p className="text-muted-foreground text-sm">{card.description}</p>
|
||||||
<div>
|
{card.referenceImageUrl ? (
|
||||||
<h4 className="font-semibold">Options</h4>
|
<Dialog>
|
||||||
<ul className="pl-4 list-disc">
|
<DialogTrigger asChild>
|
||||||
{card.options.map((option) => (
|
<button
|
||||||
<li key={option.id}>
|
type="button"
|
||||||
{option.option?.name}:{" "}
|
className="group relative overflow-hidden rounded-lg border border-border/60 bg-muted/40"
|
||||||
{option.price && option.price !== 0
|
>
|
||||||
? `${option.price}€`
|
<Image
|
||||||
: option.pricePercent
|
src={card.referenceImageUrl}
|
||||||
? `+${option.pricePercent}%`
|
alt={`${card.name} reference`}
|
||||||
: option.priceRange && option.priceRange !== "0–0"
|
width={800}
|
||||||
? `${option.priceRange}€`
|
height={600}
|
||||||
: "Included"}
|
sizes="(max-width: 768px) 90vw, 400px"
|
||||||
</li>
|
className="h-auto w-full object-cover transition-transform duration-200 group-hover:scale-[1.02]"
|
||||||
))}
|
/>
|
||||||
</ul>
|
<span className="absolute inset-x-0 bottom-0 bg-background/70 px-2 py-1 text-xs text-foreground/80">
|
||||||
</div>
|
Click to enlarge
|
||||||
|
</span>
|
||||||
<div>
|
</button>
|
||||||
{card.extras.length > 0 ? (
|
</DialogTrigger>
|
||||||
<h4 className="font-semibold">Extras</h4>
|
<DialogContent className="flex w-auto! max-w-[95vw]! flex-col p-4 sm:p-6">
|
||||||
|
<DialogHeader className="sr-only">
|
||||||
|
<DialogTitle>{card.name} reference</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="flex max-h-[85vh] max-w-[85vw] items-center justify-center rounded-xl border-border/60 bg-muted p-2 shadow-2xl">
|
||||||
|
<Image
|
||||||
|
src={card.referenceImageUrl}
|
||||||
|
alt={`${card.name} reference`}
|
||||||
|
width={1600}
|
||||||
|
height={1200}
|
||||||
|
sizes="85vw"
|
||||||
|
className="h-auto max-h-[85vh] w-auto max-w-[85vw] rounded-lg object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
) : null}
|
) : null}
|
||||||
<ul className="pl-4 list-disc">
|
</CardHeader>
|
||||||
{card.extras.map((extra) => (
|
|
||||||
<li key={extra.id}>
|
<CardContent className="flex flex-1 flex-col justify-start gap-4">
|
||||||
{extra.extra?.name}:{" "}
|
<div>
|
||||||
{extra.price && extra.price !== 0
|
<h4 className="font-semibold">Options</h4>
|
||||||
? `${extra.price}€`
|
<ul className="pl-4 list-disc">
|
||||||
: extra.pricePercent
|
{card.options.map((option) => (
|
||||||
? `+${extra.pricePercent}%`
|
<li key={option.id}>
|
||||||
: extra.priceRange && extra.priceRange !== "0–0"
|
{option.option?.name}:{" "}
|
||||||
? `${extra.priceRange}€`
|
{option.price && option.price !== 0
|
||||||
: "Included"}
|
? `${option.price}€`
|
||||||
</li>
|
: option.pricePercent
|
||||||
))}
|
? `+${option.pricePercent}%`
|
||||||
</ul>
|
: option.priceRange && option.priceRange !== "0–0"
|
||||||
</div>
|
? `${option.priceRange}€`
|
||||||
</CardContent>
|
: "Included"}
|
||||||
</Card>
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{card.extras.length > 0 ? (
|
||||||
|
<h4 className="font-semibold">Extras</h4>
|
||||||
|
) : null}
|
||||||
|
<ul className="pl-4 list-disc">
|
||||||
|
{card.extras.map((extra) => (
|
||||||
|
<li key={extra.id}>
|
||||||
|
{extra.extra?.name}:{" "}
|
||||||
|
{extra.price && extra.price !== 0
|
||||||
|
? `${extra.price}€`
|
||||||
|
: extra.pricePercent
|
||||||
|
? `+${extra.pricePercent}%`
|
||||||
|
: extra.priceRange && extra.priceRange !== "0–0"
|
||||||
|
? `${extra.priceRange}€`
|
||||||
|
: "Included"}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
@ -13,10 +14,10 @@ import {
|
|||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import type {
|
import type {
|
||||||
CommissionCustomInput,
|
|
||||||
CommissionCustomCard,
|
CommissionCustomCard,
|
||||||
CommissionCustomCardExtra,
|
CommissionCustomCardExtra,
|
||||||
CommissionCustomCardOption,
|
CommissionCustomCardOption,
|
||||||
|
CommissionCustomInput,
|
||||||
CommissionExtra,
|
CommissionExtra,
|
||||||
CommissionOption,
|
CommissionOption,
|
||||||
CommissionType,
|
CommissionType,
|
||||||
@ -319,8 +320,15 @@ export function CommissionOrderForm({ types, customCards }: Props) {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Your Name</FormLabel>
|
<FormLabel>Your Name</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="Nickname, real name, how you want to be called..." {...field} disabled={isSubmitting} />
|
<Input
|
||||||
|
placeholder="Nickname, real name, how you want to be called..."
|
||||||
|
{...field}
|
||||||
|
disabled={isSubmitting}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
This name will be visible on the commission status page.
|
||||||
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
@ -339,6 +347,9 @@ export function CommissionOrderForm({ types, customCards }: Props) {
|
|||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
Will be used for sending the invoice via paypal
|
||||||
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
@ -357,6 +368,9 @@ export function CommissionOrderForm({ types, customCards }: Props) {
|
|||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
Optional. But if filled out, we need handle and which platform. Currently supported are fediverse, bsky and telegram
|
||||||
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user