اس گائیڈ میں میٹنگ کے کمرے بک کرنے کا ایک کیلنڈر بنایا گیا ہے: ہر کمرے کی ایک قطار والی ٹائم لائن، ڈریگ کر کے ان کی جگہ پر رکھی جانے والی بکنگز، کسی کمرے کی دوہری بکنگ روکنے والا اصول، اور بکنگ کو کسی بھی کیلنڈر میں شامل کرنے والی فائل۔ اس میں @needless-ui/angular کا شیڈولر استعمال کیا گیا ہے، جو باقی Needless UI کی طرح MIT لائسنس کے تحت ہے، اس لیے ریسورس ٹائم لائن کسی بھی ایپ کے لیے مفت ہے۔

کمرے اور بکنگز

کمرے ریسورسز ہیں: ایک id، ایک title، اور باقی سب کچھ data میں۔ بکنگز سادہ ISO اوقات والے ایونٹس ہیں، جیسے 2026-10-23T09:00، اور ان کے کمرے کی id resource میں ہوتی ہے۔ ایک بکنگ میں کئی کمرے، یا لوگ، ایک فہرست کی صورت میں بھی ہو سکتے ہیں۔

ہر کمرے کی ایک قطار

دونوں کو view="timeline" کے ساتھ nui-scheduler میں پاس کریں۔ dayStart اور dayEnd دن کو کھلے رہنے کے اوقات تک محدود رکھتے ہیں، snapMinutes بکنگز کو 15 منٹ کے حساب سے منتقل کرتا ہے، اور businessHours اس وقت کو سایہ دار کرتے ہیں جب کمرے بند ہوتے ہیں۔ nuiSchedulerResource ہر قطار کا ہیڈر بناتا ہے۔

booking.html
<nui-scheduler
[events]="bookings()"
[resources]="rooms"
view="timeline"
dayStart="8"
dayEnd="19"
snapMinutes="15"
[businessHours]="hours"
editable
selectable
[allow]="free"
(slotSelect)="book($event)"
(eventChange)="move($event)"
(rangeChange)="range.set($event)"
>
<ng-template nuiSchedulerResource let-room>{{ room.title }}</ng-template>
</nui-scheduler>
<button nuiButton type="button" (click)="download()">Add to calendar</button>

بک کریں اور منتقل کریں

شیڈولر آپ کا ڈیٹا خود کبھی نہیں بدلتا: یہ صرف بتاتا ہے کہ لوگ کیا کرتے ہیں۔ کسی کمرے کی قطار پر ڈریگ کرنے سے وقت چنا جاتا ہے، اور slotSelect اسے کمرے کے ساتھ بتاتا ہے۔ کسی بکنگ کو، یا اس کے اختتامی کنارے کو، ڈریگ کرنے پر eventChange اس کے نئے اوقات بتاتا ہے، اور اگر وہ کسی دوسرے کمرے میں گئی ہو تو اس کا نیا کمرہ بھی۔ سگنل اپ ڈیٹ کریں، اور ٹائم لائن اس کے مطابق بدل جاتی ہے۔

booking.ts
import { Component, signal } from '@angular/core';
import { NuiButton } from '@needless-ui/angular/button';
import {
NuiScheduler,
type NuiSchedulerChange,
type NuiSchedulerEvent,
NuiSchedulerResourceTemplate,
type NuiSchedulerSlot,
} from '@needless-ui/angular/scheduler';
import { downloadIcs } from './booking-ics';

@Component({
selector: 'app-bookings',
imports: [NuiButton, NuiScheduler, NuiSchedulerResourceTemplate],
templateUrl: './booking.html',
})
export class Bookings {
/** Rooms are resources; bookings are events, with their room in `resource`. */
protected readonly rooms = [
{ id: 'atlas', title: 'Atlas' },
{ id: 'boreal', title: 'Boreal' },
];
protected readonly bookings = signal<NuiSchedulerEvent[]>([]);
/** Open on weekdays from 8:00 to 19:00: other time is shaded. */
protected readonly hours = [{ days: [1, 2, 3, 4, 5], start: '08:00', end: '19:00' }];
/** The days on screen: load their bookings when it changes. */
protected readonly range = signal<{ start: string; end: string } | null>(null);

protected book({ start, end, resource }: NuiSchedulerSlot): void {
const booking = { id: crypto.randomUUID(), title: 'New booking', start, end, resource };
this.bookings.update((all) => [...all, booking]);
}

protected move({ event, start, end, resource }: NuiSchedulerChange): void {
this.bookings.update((all) =>
all.map((b) =>
b.id === event.id ? { ...b, start, end, resource: resource ?? b.resource } : b,
),
);
}

/** A room holds one booking at a time. */
protected readonly free = (time: NuiSchedulerChange | NuiSchedulerSlot): boolean => {
const id = 'event' in time ? time.event.id : null;
const room = 'event' in time ? (time.resource ?? time.event.resource) : time.resource;
return !this.bookings().some(
(b) => b.id !== id && b.resource === room && b.start < time.end && b.end > time.start,
);
};

protected download(): void {
downloadIcs(this.bookings(), 'bookings');
}
}

کوئی دوہری بکنگ نہیں

کوئی بکنگ بنانے یا منتقل کرنے سے پہلے allow سے پوچھا جاتا ہے۔ جب یہ false لوٹاتا ہے تو ڈریگ سرخ دکھائی دیتا ہے اور چھوڑنے پر کچھ نہیں ہوتا، اور کی بورڈ سے کوشش کرنے پر شیڈولر بتاتا ہے کہ یہ وقت دستیاب نہیں۔ مثال کمرے کی دوسری بکنگز چیک کرتی ہے؛ اپنے سرور پر دوبارہ چیک کریں، کیونکہ آخری فیصلہ اسی کا ہوتا ہے۔

اسکرین پر موجود دن لوڈ کریں

rangeChange دکھائے گئے پہلے اور آخری دن بتاتا ہے، ایک بار شروع میں اور پھر جب بھی لوگ صفحہ بدلیں، تاکہ آپ صرف انہی دنوں کی بکنگز لا سکیں، httpResource سے یا اپنی پسند کی کسی بھی ریکویسٹ سے۔

کیلنڈر میں شامل کریں

nuiSchedulerToIcs() بکنگز کو iCalendar فائل کے طور پر لکھتا ہے، جسے Google Calendar، Outlook اور Apple Calendar امپورٹ کرتے ہیں۔ nuiSchedulerFromIcs() ایسی فائل واپس پڑھتا ہے، اور دوسرے ٹائم زونز کے اوقات کو صارف کے اپنے ٹائم زون میں لے آتا ہے۔

booking-ics.ts
import { type NuiSchedulerEvent, nuiSchedulerToIcs } from '@needless-ui/angular/scheduler';

/** Saves events as an .ics file, which Google Calendar, Outlook and Apple Calendar import. */
export function downloadIcs(events: readonly NuiSchedulerEvent[], name: string): void {
const file = new Blob([nuiSchedulerToIcs(events, { name })], { type: 'text/calendar' });
const link = document.createElement('a');
link.href = URL.createObjectURL(file);
link.download = `${name}.ics`;
link.click();
URL.revokeObjectURL(link.href);
}

کی بورڈ اور اسکرین ریڈرز

یہ سب ماؤس کے بغیر بھی کام کرتا ہے۔ ٹائم لائن ایک ہی ٹیب اسٹاپ ہے: ایرو کیز اوقات اور کمروں کے درمیان لے جاتی ہیں، Shift کے ساتھ ایرو کیز وقت چنتی ہیں، اور Enter اسے بک کرتا ہے۔ کسی بکنگ پر، Alt کے ساتھ ایرو کیز اسے کسی دوسرے وقت یا کمرے میں منتقل کرتی ہیں۔ ہر بکنگ ایک بٹن ہے جس کا نام اس کے عنوان، کمرے، دن اور وقت سے بنتا ہے۔

دن کے منظر میں ساتھ ساتھ کمروں، بار بار ہونے والی بکنگز اور باقی تمام آپشنز کے لیے شیڈولر کا صفحہ اور اس کا API دیکھیں۔