feat(webDev): add inquiry modal for pricing plans

This commit introduces a 'Contact Sales' modal on the web development page, allowing users to inquire about specific service plans.

- The pricing plan buttons now trigger this modal, pre-filled with the selected plan's details.
- Users can add custom remarks to their inquiry.
- On submission, a pre-formatted message is generated and opened in WhatsApp using a new `useWhatsAppMsgSender` composable.
- Adds `NUXT_PUBLIC_WHATSAPP_NUMBER` to the runtime configuration.
- Refactors content validation by introducing Zod schemas for `PricingPlan` and `Button` props to improve type safety.
- Adds new i18n keys for the modal interface and message templates.
This commit is contained in:
xiaomai
2025-11-07 11:04:14 +08:00
parent 40b3ee147f
commit ccfd268682
14 changed files with 393 additions and 40 deletions

View File

@@ -0,0 +1,37 @@
// buttonSchema.ts
import { z } from "zod";
const ButtonSize = z.enum(["2xs", "xs", "sm", "md", "lg", "xl"]);
const ButtonColor = z.enum([
"error",
"primary",
"secondary",
"success",
"info",
"warning",
"neutral",
]);
const ButtonVariant = z.enum(["solid", "outline", "soft", "ghost", "link"]);
export const ButtonPropsSchema = z.object({
size: ButtonSize.optional().default("sm"),
type: z.enum(["button", "submit", "reset"]).optional().default("button"),
label: z.string().optional().default(""),
color: ButtonColor.optional().default("primary"),
variant: ButtonVariant.optional().default("solid"),
icon: z.string().optional().default(""),
leading: z.boolean().optional().default(false),
trailing: z.boolean().optional().default(false),
disabled: z.boolean().optional().default(false),
loading: z.boolean().optional().default(false),
loadingIcon: z.string().optional().default("i-heroicons-arrow-path-20-solid"),
block: z.boolean().optional().default(false),
to: z.string().optional().default(""),
target: z.string().optional().default(""),
padded: z.boolean().optional().default(true),
square: z.boolean().optional().default(false),
truncate: z.boolean().optional().default(false),
attrs: z.record(z.any()).optional().default({}),
});
export type ButtonProps = z.infer<typeof ButtonPropsSchema>;