Finish with url copying
This commit is contained in:
parent
27dc530b1c
commit
8d9c7332b3
6 changed files with 91 additions and 1 deletions
|
|
@ -145,6 +145,7 @@ export type Database = {
|
|||
deleted_at: string | null
|
||||
id: string
|
||||
is_active: boolean
|
||||
standard_name: string | null
|
||||
updated_at: string | null
|
||||
user_id: string
|
||||
}
|
||||
|
|
@ -154,6 +155,7 @@ export type Database = {
|
|||
deleted_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
standard_name?: string | null
|
||||
updated_at?: string | null
|
||||
user_id: string
|
||||
}
|
||||
|
|
@ -163,6 +165,7 @@ export type Database = {
|
|||
deleted_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
standard_name?: string | null
|
||||
updated_at?: string | null
|
||||
user_id?: string
|
||||
}
|
||||
|
|
|
|||
44
sql/19_standard_name.sql
Normal file
44
sql/19_standard_name.sql
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
-- Add standard_name column to event_types table
|
||||
-- This column should not be modifiable by authenticated users
|
||||
|
||||
-- Add the standard_name column
|
||||
ALTER TABLE event_types ADD COLUMN standard_name TEXT;
|
||||
|
||||
-- Add comment for the new column
|
||||
COMMENT ON COLUMN event_types.standard_name IS
|
||||
'Standard name for the event type - not modifiable by authenticated users';
|
||||
|
||||
-- Create function to automatically set standard_name on insert and prevent modification by authenticated users
|
||||
CREATE OR REPLACE FUNCTION handle_event_types_standard_name()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
-- On INSERT: automatically set standard_name from config->>'name', sanitized
|
||||
IF TG_OP = 'INSERT' THEN
|
||||
-- Extract name from config and sanitize it (replace spaces with hyphens, lowercase)
|
||||
NEW.standard_name = LOWER(REPLACE(TRIM(NEW.config->>'name'), ' ', '-'));
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
-- On UPDATE: prevent standard_name modification by authenticated users
|
||||
IF TG_OP = 'UPDATE' THEN
|
||||
-- Only allow system/service role to modify standard_name
|
||||
-- If the current user is authenticated (not service_role), prevent standard_name changes
|
||||
IF current_setting('role') != 'service_role' AND OLD.standard_name IS DISTINCT FROM NEW.standard_name THEN RAISE EXCEPTION 'standard_name column cannot be modified'; END IF;
|
||||
|
||||
-- If name in config changes, update standard_name accordingly (but only for non-authenticated users)
|
||||
IF current_setting('role') = 'service_role' AND OLD.config->>'name' IS DISTINCT FROM NEW.config->>'name' THEN
|
||||
NEW.standard_name = LOWER(REPLACE(TRIM(NEW.config->>'name'), ' ', '-'));
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
-- Create trigger to handle standard_name on insert and prevent modification on update
|
||||
CREATE TRIGGER handle_event_types_standard_name_trigger
|
||||
BEFORE INSERT OR UPDATE ON event_types
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION handle_event_types_standard_name();
|
||||
|
||||
|
||||
|
|
@ -20,6 +20,7 @@ export type EventType = {
|
|||
value: number;
|
||||
unit: "minutes" | "hours" | "days";
|
||||
}; // minimum hours in advance
|
||||
standardName: string;
|
||||
};
|
||||
|
||||
const QUERY_KEY = ["event-types"];
|
||||
|
|
@ -140,6 +141,7 @@ export function useEventTypes() {
|
|||
...eventTypeConfig,
|
||||
isActive: eventType.is_active,
|
||||
id: eventType.id,
|
||||
standardName: eventType.standard_name,
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,21 @@
|
|||
import { useState } from "react";
|
||||
import { Strong, Text } from "@ui/ui-library/text";
|
||||
import { Button, ToggleButton } from "@ui/ui-library/button";
|
||||
import { PlusIcon, EditIcon, TrashIcon, CheckIcon, XIcon } from "lucide-react";
|
||||
import {
|
||||
PlusIcon,
|
||||
EditIcon,
|
||||
TrashIcon,
|
||||
CheckIcon,
|
||||
XIcon,
|
||||
LinkIcon,
|
||||
} from "lucide-react";
|
||||
import { toast } from "@ui/ui-library/toast/toast-queue";
|
||||
import { EventTypeModal } from "@ui/components/EventTypeModal";
|
||||
import { EventType, useEventTypes } from "@ui/hooks/event-types";
|
||||
import { useUser } from "@ui/providers/UserStoreProvider";
|
||||
|
||||
export function EventTypesPage() {
|
||||
const user = useUser();
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [editingEventType, setEditingEventType] = useState<EventType | null>(
|
||||
null
|
||||
|
|
@ -71,6 +80,23 @@ export function EventTypesPage() {
|
|||
setEditingEventType(null);
|
||||
};
|
||||
|
||||
const handleOpenPublicLink = (eventType: EventType) => {
|
||||
// Sanitize user name for URL (replace spaces with hyphens, lowercase, remove special chars)
|
||||
const sanitizedUserName = user.name
|
||||
?.toLowerCase()
|
||||
.replace(/\s+/g, "-")
|
||||
.replace(/[^a-z0-9-]/g, "");
|
||||
|
||||
const shortUserId = user.id.substring(0, 6);
|
||||
// Construct the public booking URL
|
||||
const baseUrl = window.location.origin;
|
||||
const publicUrl = `${baseUrl}/book/${sanitizedUserName}-${shortUserId}/${eventType.standardName}`;
|
||||
console.log(publicUrl);
|
||||
|
||||
// Open in new tab
|
||||
// window.open(publicUrl, "_blank");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col p-4">
|
||||
<div className="flex justify-between items-start mb-6">
|
||||
|
|
@ -104,6 +130,15 @@ export function EventTypesPage() {
|
|||
<h3 className="text-lg font-semibold">{eventType.name}</h3>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant="plain"
|
||||
isIconOnly
|
||||
onPress={() => handleOpenPublicLink(eventType as EventType)}
|
||||
className="text-gray-500 hover:text-green-600"
|
||||
tooltip="Ouvrir le lien de réservation public"
|
||||
>
|
||||
<LinkIcon className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="plain"
|
||||
isIconOnly
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ export type Database = {
|
|||
deleted_at: string | null
|
||||
id: string
|
||||
is_active: boolean
|
||||
standard_name: string | null
|
||||
updated_at: string | null
|
||||
user_id: string
|
||||
}
|
||||
|
|
@ -154,6 +155,7 @@ export type Database = {
|
|||
deleted_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
standard_name?: string | null
|
||||
updated_at?: string | null
|
||||
user_id: string
|
||||
}
|
||||
|
|
@ -163,6 +165,7 @@ export type Database = {
|
|||
deleted_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
standard_name?: string | null
|
||||
updated_at?: string | null
|
||||
user_id?: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ export type Database = {
|
|||
deleted_at: string | null
|
||||
id: string
|
||||
is_active: boolean
|
||||
standard_name: string | null
|
||||
updated_at: string | null
|
||||
user_id: string
|
||||
}
|
||||
|
|
@ -154,6 +155,7 @@ export type Database = {
|
|||
deleted_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
standard_name?: string | null
|
||||
updated_at?: string | null
|
||||
user_id: string
|
||||
}
|
||||
|
|
@ -163,6 +165,7 @@ export type Database = {
|
|||
deleted_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
standard_name?: string | null
|
||||
updated_at?: string | null
|
||||
user_id?: string
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue