edit time rezerv
This commit is contained in:
@@ -12,6 +12,49 @@ const TEHRAN_WEEKDAY: Record<string, number> = {
|
||||
};
|
||||
|
||||
const TIME_RE = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
||||
const PERSIAN_DIGITS = '۰۱۲۳۴۵۶۷۸۹';
|
||||
const ARABIC_DIGITS = '٠١٢٣٤٥٦٧٨٩';
|
||||
|
||||
function toAsciiDigits(value: string): string {
|
||||
return value.replace(/./g, (ch) => {
|
||||
const pi = PERSIAN_DIGITS.indexOf(ch);
|
||||
if (pi >= 0) return String(pi);
|
||||
const ai = ARABIC_DIGITS.indexOf(ch);
|
||||
if (ai >= 0) return String(ai);
|
||||
return ch;
|
||||
});
|
||||
}
|
||||
|
||||
/** Accepts browser variants (9:00, 09:00:00, Persian digits) → HH:mm */
|
||||
export function normalizeHmTimeInput(value: unknown): string | null {
|
||||
if (value == null || value === '') return null;
|
||||
let raw = toAsciiDigits(String(value).trim()).normalize('NFKC');
|
||||
raw = raw.replace(/[\u200e\u200f\u202a\u202c]/g, '');
|
||||
|
||||
const ampm = /^(\d{1,2}):(\d{1,2})(?::\d{1,2})?\s*([ap])(?:\.)?m?\.?$/i.exec(
|
||||
raw,
|
||||
);
|
||||
if (ampm) {
|
||||
let h = Number.parseInt(ampm[1], 10);
|
||||
const m = Number.parseInt(ampm[2], 10);
|
||||
const isPm = ampm[3].toLowerCase() === 'p';
|
||||
if (h === 12) h = isPm ? 12 : 0;
|
||||
else if (isPm) h += 12;
|
||||
if (h < 0 || h > 23 || m < 0 || m > 59) return null;
|
||||
return minuteToHm(h * 60 + m);
|
||||
}
|
||||
|
||||
const match = /^(\d{1,2}):(\d{1,2})(?::\d{1,2})?$/.exec(raw);
|
||||
if (!match) return null;
|
||||
let h = Number.parseInt(match[1], 10);
|
||||
const m = Number.parseInt(match[2], 10);
|
||||
if (h === 24 && m === 0) {
|
||||
h = 23;
|
||||
return '23:59';
|
||||
}
|
||||
if (h < 0 || h > 23 || m < 0 || m > 59) return null;
|
||||
return minuteToHm(h * 60 + m);
|
||||
}
|
||||
|
||||
export type AvailabilityWindow = {
|
||||
dayOfWeek: number;
|
||||
@@ -25,7 +68,8 @@ export type BusyInterval = {
|
||||
};
|
||||
|
||||
export function parseHmToMinute(value: string): number {
|
||||
const match = TIME_RE.exec(String(value).trim());
|
||||
const normalized = normalizeHmTimeInput(value);
|
||||
const match = TIME_RE.exec(normalized ?? '');
|
||||
if (!match) {
|
||||
throw new BadRequestException('Time must be HH:mm (24h)');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class CreateBusinessAvailabilitySlots1789043000000
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'CreateBusinessAvailabilitySlots1789043000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS "business_availability_slots" (
|
||||
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
||||
"businessId" uuid NOT NULL,
|
||||
"dayOfWeek" smallint NOT NULL,
|
||||
"startMinute" integer NOT NULL,
|
||||
"endMinute" integer NOT NULL,
|
||||
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "PK_business_availability_slots" PRIMARY KEY ("id"),
|
||||
CONSTRAINT "FK_availability_business" FOREIGN KEY ("businessId")
|
||||
REFERENCES "businesses"("id") ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_availability_business_day"
|
||||
ON "business_availability_slots" ("businessId", "dayOfWeek")
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "business_availability_slots"`);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { Transform, Type } from 'class-transformer';
|
||||
import {
|
||||
ArrayMaxSize,
|
||||
IsArray,
|
||||
@@ -10,20 +10,24 @@ import {
|
||||
Min,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { normalizeHmTimeInput } from '../../../common/utils/booking-schedule.util';
|
||||
|
||||
export class AvailabilitySlotDto {
|
||||
@ApiProperty({ description: '0=شنبه … 6=جمعه', minimum: 0, maximum: 6 })
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@Max(6)
|
||||
dayOfWeek!: number;
|
||||
|
||||
@ApiProperty({ example: '09:00' })
|
||||
@Transform(({ value }) => normalizeHmTimeInput(value) ?? value)
|
||||
@IsString()
|
||||
@Matches(/^([01]\d|2[0-3]):[0-5]\d]$/)
|
||||
startTime!: string;
|
||||
|
||||
@ApiProperty({ example: '17:00' })
|
||||
@Transform(({ value }) => normalizeHmTimeInput(value) ?? value)
|
||||
@IsString()
|
||||
@Matches(/^([01]\d|2[0-3]):[0-5]\d]$/)
|
||||
endTime!: string;
|
||||
|
||||
Reference in New Issue
Block a user