@back23/promptly-sdk 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,17 @@
1
- # @webbyon/promptly-sdk
1
+ # @back23/promptly-sdk
2
2
 
3
3
  Promptly AI CMS SDK for JavaScript/TypeScript
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @webbyon/promptly-sdk
8
+ npm install @back23/promptly-sdk
9
9
  ```
10
10
 
11
11
  ## Quick Start
12
12
 
13
13
  ```typescript
14
- import { Promptly } from '@webbyon/promptly-sdk';
14
+ import { Promptly } from '@back23/promptly-sdk';
15
15
 
16
16
  const client = new Promptly({
17
17
  tenantId: 'demo',
@@ -19,6 +19,38 @@ const client = new Promptly({
19
19
  });
20
20
  ```
21
21
 
22
+ ## v1.3.0 Changes
23
+
24
+ ### Unified Response Structure
25
+
26
+ All list APIs now return a consistent `ListResponse<T>` format:
27
+
28
+ ```typescript
29
+ interface ListResponse<T> {
30
+ data: T[]; // Always an array (never null/undefined)
31
+ meta: {
32
+ current_page: number;
33
+ last_page: number;
34
+ per_page: number;
35
+ total: number;
36
+ from: number | null;
37
+ to: number | null;
38
+ };
39
+ }
40
+ ```
41
+
42
+ **No more defensive code needed:**
43
+
44
+ ```typescript
45
+ // Before (v1.1.0)
46
+ const posts = await client.blog.list();
47
+ const items = posts?.data ?? []; // Defensive check needed
48
+
49
+ // After (v1.3.0)
50
+ const { data, meta } = await client.blog.list();
51
+ data.map(post => ...); // data is always an array
52
+ ```
53
+
22
54
  ## API Overview
23
55
 
24
56
  | Resource | Public (No Auth) | Protected (Auth Required) |
@@ -26,12 +58,13 @@ const client = new Promptly({
26
58
  | **Boards** | list, get | - |
27
59
  | **Posts** | listPosts, getPost | createPost, updatePost, deletePost |
28
60
  | **Comments** | listComments | createComment, updateComment, deleteComment |
29
- | **Blog** | list, get | - |
61
+ | **Blog** | list, get, featured, byCategory, byTag | - |
30
62
  | **Shop** | listProducts, getProduct, listCategories | getCart, addToCart, listOrders, createOrder |
31
63
  | **Forms** | list, get, submit | mySubmissions |
32
64
  | **Auth** | login, register | logout, me, updateProfile |
33
65
  | **Media** | - | upload, list, delete |
34
66
  | **Entities** | list, getSchema, listRecords, getRecord | createRecord, updateRecord, deleteRecord |
67
+ | **Reservation** | getSettings, listServices, listStaff, getAvailableDates, getAvailableSlots | create, list, get, cancel |
35
68
 
36
69
  ## API Reference
37
70
 
@@ -39,20 +72,20 @@ const client = new Promptly({
39
72
 
40
73
  ```typescript
41
74
  // 게시판 목록
42
- const boards = await client.boards.list();
43
- // Returns: Board[]
75
+ const { data: boards, meta } = await client.boards.list();
76
+ // Returns: ListResponse<Board>
44
77
 
45
78
  // 게시판 상세
46
79
  const board = await client.boards.get('first'); // slug or id
47
80
  // Returns: Board
48
81
 
49
82
  // 게시판 글 목록
50
- const posts = await client.boards.listPosts('first', {
83
+ const { data: posts, meta } = await client.boards.listPosts('first', {
51
84
  page: 1,
52
85
  per_page: 10,
53
86
  search: '검색어', // optional
54
87
  });
55
- // Returns: { data: BoardPost[], meta: { current_page, last_page, per_page, total } }
88
+ // Returns: ListResponse<BoardPost>
56
89
 
57
90
  // 글 상세
58
91
  const post = await client.boards.getPost(1);
@@ -60,7 +93,7 @@ const post = await client.boards.getPost(1);
60
93
 
61
94
  // 댓글 목록
62
95
  const comments = await client.boards.listComments(1);
63
- // Returns: BoardComment[]
96
+ // Returns: BoardComment[] (always an array)
64
97
  ```
65
98
 
66
99
  ### Posts & Comments - Protected (로그인 필요)
@@ -105,14 +138,14 @@ await client.boards.deleteComment(commentId);
105
138
 
106
139
  ```typescript
107
140
  // 블로그 글 목록
108
- const posts = await client.blog.list({
141
+ const { data: posts, meta } = await client.blog.list({
109
142
  page: 1,
110
143
  per_page: 10,
111
144
  category: 'news', // optional
112
145
  tag: 'featured', // optional
113
146
  search: '검색어', // optional
114
147
  });
115
- // Returns: { data: BlogPost[], meta: {...} }
148
+ // Returns: ListResponse<BlogPost>
116
149
 
117
150
  // 블로그 글 상세
118
151
  const post = await client.blog.get('post-slug');
@@ -120,13 +153,21 @@ const post = await client.blog.get('post-slug');
120
153
 
121
154
  // 추천 글
122
155
  const featured = await client.blog.featured(5);
123
- // Returns: BlogPost[]
156
+ // Returns: BlogPost[] (always an array)
124
157
 
125
158
  // 카테고리별 조회
126
- const newsPosts = await client.blog.byCategory('news');
159
+ const { data: newsPosts } = await client.blog.byCategory('news');
127
160
 
128
161
  // 태그별 조회
129
- const taggedPosts = await client.blog.byTag('featured');
162
+ const { data: taggedPosts } = await client.blog.byTag('featured');
163
+
164
+ // 카테고리 목록
165
+ const categories = await client.blog.categories();
166
+ // Returns: string[] (always an array)
167
+
168
+ // 태그 목록
169
+ const tags = await client.blog.tags();
170
+ // Returns: string[] (always an array)
130
171
  ```
131
172
 
132
173
  ### Shop (쇼핑)
@@ -135,14 +176,14 @@ const taggedPosts = await client.blog.byTag('featured');
135
176
 
136
177
  ```typescript
137
178
  // 상품 목록
138
- const products = await client.shop.listProducts({
179
+ const { data: products, meta } = await client.shop.listProducts({
139
180
  page: 1,
140
181
  per_page: 10,
141
182
  category: 'electronics', // optional
142
183
  is_featured: true, // optional
143
184
  search: '검색어', // optional
144
185
  });
145
- // Returns: { data: Product[], meta: {...} }
186
+ // Returns: ListResponse<Product>
146
187
 
147
188
  // 상품 상세
148
189
  const product = await client.shop.getProduct('product-slug');
@@ -150,11 +191,11 @@ const product = await client.shop.getProduct('product-slug');
150
191
 
151
192
  // 추천 상품
152
193
  const featured = await client.shop.featuredProducts(8);
153
- // Returns: Product[]
194
+ // Returns: Product[] (always an array)
154
195
 
155
196
  // 카테고리 목록
156
197
  const categories = await client.shop.listCategories();
157
- // Returns: ProductCategory[]
198
+ // Returns: ProductCategory[] (always an array)
158
199
  ```
159
200
 
160
201
  #### Protected (로그인 필요)
@@ -195,8 +236,8 @@ const order = await client.shop.createOrder({
195
236
  });
196
237
 
197
238
  // 주문 목록
198
- const orders = await client.shop.listOrders();
199
- // Returns: { data: Order[], meta: {...} }
239
+ const { data: orders, meta } = await client.shop.listOrders();
240
+ // Returns: ListResponse<Order>
200
241
 
201
242
  // 주문 상세
202
243
  const order = await client.shop.getOrder(orderId);
@@ -208,6 +249,89 @@ await client.shop.cancelOrder(orderId);
208
249
  // 쿠폰 검증
209
250
  const validation = await client.shop.validateCoupon('SAVE10', 50000);
210
251
  // Returns: { valid: boolean, discount_amount: number, coupon: Coupon }
252
+
253
+ // 내 쿠폰 목록
254
+ const coupons = await client.shop.myCoupons();
255
+ // Returns: Coupon[] (always an array)
256
+ ```
257
+
258
+ ### Reservation (예약) - NEW in v1.3.0
259
+
260
+ #### Public (로그인 불필요)
261
+
262
+ ```typescript
263
+ // 예약 설정 조회
264
+ const settings = await client.reservation.getSettings();
265
+ // Returns: ReservationSettings
266
+
267
+ // 서비스 목록
268
+ const services = await client.reservation.listServices();
269
+ // Returns: ReservationService[] (always an array)
270
+
271
+ // 담당자 목록
272
+ const staffs = await client.reservation.listStaff();
273
+ // Returns: ReservationStaff[] (always an array)
274
+
275
+ // 특정 서비스의 담당자만 조회
276
+ const serviceStaffs = await client.reservation.listStaff(serviceId);
277
+
278
+ // 예약 가능 날짜 조회
279
+ const dates = await client.reservation.getAvailableDates({
280
+ service_id: 1,
281
+ staff_id: 2, // optional
282
+ start_date: '2026-01-01', // optional
283
+ end_date: '2026-01-31', // optional
284
+ });
285
+ // Returns: string[] (YYYY-MM-DD format)
286
+
287
+ // 예약 가능 시간 슬롯 조회
288
+ const slots = await client.reservation.getAvailableSlots({
289
+ service_id: 1,
290
+ date: '2026-01-15',
291
+ staff_id: 2, // optional
292
+ });
293
+ // Returns: ReservationSlot[]
294
+ ```
295
+
296
+ #### Protected (로그인 필요)
297
+
298
+ ```typescript
299
+ // 예약 생성
300
+ const result = await client.reservation.create({
301
+ service_id: 1,
302
+ staff_id: 2, // optional
303
+ reservation_date: '2026-01-15',
304
+ start_time: '14:00',
305
+ customer_name: '홍길동',
306
+ customer_phone: '010-1234-5678', // optional
307
+ customer_email: 'hong@example.com', // optional
308
+ customer_memo: '요청사항', // optional
309
+ });
310
+ // Returns: { reservation: Reservation, requires_payment: boolean, deposit: number }
311
+
312
+ // 내 예약 목록
313
+ const { data: reservations, meta } = await client.reservation.list({
314
+ status: 'confirmed', // optional
315
+ upcoming: true, // optional
316
+ past: false, // optional
317
+ });
318
+ // Returns: ListResponse<Reservation>
319
+
320
+ // 다가오는 예약
321
+ const upcoming = await client.reservation.upcoming(5);
322
+ // Returns: Reservation[] (always an array)
323
+
324
+ // 지난 예약
325
+ const past = await client.reservation.past(10);
326
+ // Returns: Reservation[] (always an array)
327
+
328
+ // 예약 상세
329
+ const reservation = await client.reservation.get('RES-20260115-001');
330
+ // Returns: Reservation
331
+
332
+ // 예약 취소
333
+ const cancelled = await client.reservation.cancel('RES-20260115-001', '일정 변경');
334
+ // Returns: Reservation
211
335
  ```
212
336
 
213
337
  ### Auth (인증)
@@ -280,8 +404,8 @@ const response = await client.auth.socialCallback('google', code);
280
404
 
281
405
  ```typescript
282
406
  // 폼 목록
283
- const forms = await client.forms.list();
284
- // Returns: Form[]
407
+ const { data: forms } = await client.forms.list();
408
+ // Returns: ListResponse<Form>
285
409
 
286
410
  // 폼 상세
287
411
  const form = await client.forms.get('contact');
@@ -293,6 +417,10 @@ await client.forms.submit('contact', {
293
417
  email: 'user@example.com',
294
418
  message: '문의 내용',
295
419
  });
420
+
421
+ // 내 제출 목록 (로그인 필요)
422
+ const { data: submissions } = await client.forms.mySubmissions();
423
+ // Returns: ListResponse<FormSubmission>
296
424
  ```
297
425
 
298
426
  ### Media (미디어) - Protected
@@ -307,12 +435,12 @@ const mediaList = await client.media.uploadMultiple([file1, file2]);
307
435
  // Returns: Media[]
308
436
 
309
437
  // 내 미디어 목록
310
- const mediaList = await client.media.list({
438
+ const { data: mediaList, meta } = await client.media.list({
311
439
  page: 1,
312
440
  per_page: 20,
313
441
  type: 'image/jpeg', // optional
314
442
  });
315
- // Returns: { data: Media[], meta: {...} }
443
+ // Returns: ListResponse<Media>
316
444
 
317
445
  // 미디어 삭제
318
446
  await client.media.delete(mediaId);
@@ -327,22 +455,22 @@ AI가 MCP를 통해 생성한 커스텀 데이터 구조에 접근합니다.
327
455
  ```typescript
328
456
  // 엔티티 목록 조회
329
457
  const entities = await client.entities.list();
330
- // Returns: CustomEntity[]
458
+ // Returns: CustomEntity[] (always an array)
331
459
 
332
460
  // 엔티티 스키마 조회
333
461
  const schema = await client.entities.getSchema('customer');
334
462
  // Returns: EntitySchema
335
463
 
336
464
  // 레코드 목록 조회
337
- const customers = await client.entities.listRecords('customer', {
465
+ const { data: customers, meta } = await client.entities.listRecords('customer', {
338
466
  page: 1,
339
467
  per_page: 20,
340
468
  status: 'active',
341
469
  });
342
- // Returns: { data: EntityRecord[], meta: {...} }
470
+ // Returns: ListResponse<EntityRecord>
343
471
 
344
472
  // 데이터 필드로 필터링
345
- const vipCustomers = await client.entities.listRecords('customer', {
473
+ const { data: vipCustomers } = await client.entities.listRecords('customer', {
346
474
  'data.tier': 'vip',
347
475
  });
348
476
 
@@ -415,6 +543,27 @@ const settings = await client.getSettings();
415
543
 
416
544
  ## Types
417
545
 
546
+ ### Common Types
547
+
548
+ ```typescript
549
+ // Unified list response type
550
+ interface ListResponse<T> {
551
+ data: T[];
552
+ meta: PaginationMeta;
553
+ }
554
+
555
+ interface PaginationMeta {
556
+ current_page: number;
557
+ last_page: number;
558
+ per_page: number;
559
+ total: number;
560
+ from: number | null;
561
+ to: number | null;
562
+ }
563
+ ```
564
+
565
+ ### Resource Types
566
+
418
567
  ```typescript
419
568
  interface Board {
420
569
  id: number;
@@ -440,16 +589,6 @@ interface BoardPost {
440
589
  created_at: string;
441
590
  }
442
591
 
443
- interface BoardComment {
444
- id: number;
445
- post_id: number;
446
- member?: Member;
447
- parent_id?: number;
448
- content: string;
449
- replies?: BoardComment[];
450
- created_at: string;
451
- }
452
-
453
592
  interface BlogPost {
454
593
  id: number;
455
594
  slug: string;
@@ -463,8 +602,6 @@ interface BlogPost {
463
602
  is_published: boolean;
464
603
  published_at?: string;
465
604
  view_count: number;
466
- seo_title?: string;
467
- seo_description?: string;
468
605
  created_at: string;
469
606
  }
470
607
 
@@ -473,38 +610,60 @@ interface Product {
473
610
  slug: string;
474
611
  name: string;
475
612
  description?: string;
476
- content?: string;
477
613
  price: number;
478
614
  compare_price?: number;
479
615
  thumbnail?: string;
480
616
  images?: string[];
481
617
  status: 'draft' | 'active' | 'inactive';
482
618
  is_featured: boolean;
483
- has_options: boolean;
484
- variants?: ProductVariant[];
485
619
  in_stock?: boolean;
486
620
  discount_percent?: number;
487
621
  created_at: string;
488
622
  }
489
623
 
490
- interface Cart {
624
+ interface Reservation {
491
625
  id: number;
492
- items: CartItem[];
493
- total: number;
494
- total_quantity: number;
495
- item_count: number;
626
+ reservation_number: string;
627
+ status: 'pending' | 'confirmed' | 'completed' | 'cancelled' | 'no_show';
628
+ status_label: string;
629
+ reservation_date: string;
630
+ start_time: string;
631
+ end_time: string;
632
+ time_range: string;
633
+ customer_name: string;
634
+ customer_phone: string | null;
635
+ customer_email: string | null;
636
+ price: number;
637
+ deposit: number;
638
+ payment_status: 'pending' | 'paid' | 'refunded' | 'partial';
639
+ can_cancel: boolean;
640
+ service: { id: number; name: string; duration: number; } | null;
641
+ staff: { id: number; name: string; avatar: string | null; } | null;
642
+ created_at: string;
496
643
  }
497
644
 
498
- interface Order {
645
+ interface ReservationService {
499
646
  id: number;
500
- order_number: string;
501
- status: 'pending' | 'paid' | 'preparing' | 'shipping' | 'delivered' | 'cancelled';
502
- subtotal: number;
503
- discount_amount: number;
504
- shipping_fee: number;
505
- total: number;
506
- items?: OrderItem[];
507
- created_at: string;
647
+ name: string;
648
+ slug: string;
649
+ description: string | null;
650
+ thumbnail: string | null;
651
+ duration: number;
652
+ price: number;
653
+ requires_staff: boolean;
654
+ requires_payment: boolean;
655
+ deposit: number;
656
+ staffs: Array<{ id: number; name: string; avatar: string | null; }>;
657
+ }
658
+
659
+ interface ReservationSettings {
660
+ timezone: string;
661
+ slot_interval: number;
662
+ min_notice_hours: number;
663
+ max_advance_days: number;
664
+ cancellation_hours: number;
665
+ allow_online_payment: boolean;
666
+ bookable_date_range: { start: string; end: string; };
508
667
  }
509
668
 
510
669
  interface Member {
@@ -517,56 +676,16 @@ interface Member {
517
676
  created_at: string;
518
677
  }
519
678
 
520
- interface Form {
521
- id: number;
522
- slug: string;
523
- name: string;
524
- description?: string;
525
- fields: FormField[];
526
- settings: FormSettings;
527
- is_active: boolean;
528
- }
529
-
530
- interface Media {
531
- id: number;
532
- url: string;
533
- thumbnail_url?: string;
534
- filename: string;
535
- mime_type: string;
536
- size: number;
537
- created_at: string;
538
- }
539
-
540
679
  interface CustomEntity {
541
680
  id: number;
542
681
  name: string;
543
682
  slug: string;
544
683
  description?: string;
545
684
  schema: EntitySchema;
546
- icon?: string;
547
685
  is_active: boolean;
548
- records_count?: number;
549
686
  created_at: string;
550
687
  }
551
688
 
552
- interface EntitySchema {
553
- fields: EntityField[];
554
- display?: {
555
- title_field?: string;
556
- list_fields?: string;
557
- };
558
- }
559
-
560
- interface EntityField {
561
- name: string;
562
- label: string;
563
- type: 'text' | 'textarea' | 'number' | 'email' | 'url' | 'date' | 'datetime' | 'boolean' | 'select' | 'multiselect';
564
- required?: boolean;
565
- searchable?: boolean;
566
- default?: any;
567
- options?: Array<{ value: string; label: string }>;
568
- }
569
-
570
689
  interface EntityRecord {
571
690
  id: number;
572
691
  entity_id: number;
@@ -580,7 +699,7 @@ interface EntityRecord {
580
699
  ## Error Handling
581
700
 
582
701
  ```typescript
583
- import { Promptly, PromptlyError } from '@webbyon/promptly-sdk';
702
+ import { Promptly, PromptlyError } from '@back23/promptly-sdk';
584
703
 
585
704
  try {
586
705
  await client.auth.login({ email: 'wrong@email.com', password: 'wrong' });
@@ -597,107 +716,106 @@ try {
597
716
 
598
717
  ```tsx
599
718
  import { useState, useEffect } from 'react';
600
- import { Promptly } from '@webbyon/promptly-sdk';
719
+ import { Promptly } from '@back23/promptly-sdk';
601
720
 
602
721
  const client = new Promptly({
603
722
  tenantId: 'demo',
604
723
  baseUrl: 'https://promptly.webbyon.com',
605
724
  });
606
725
 
607
- // 게시판 글 목록
608
- function BoardPosts({ boardSlug }) {
726
+ // 블로그 글 목록 (with pagination)
727
+ function BlogList() {
609
728
  const [posts, setPosts] = useState([]);
610
- const [loading, setLoading] = useState(true);
729
+ const [meta, setMeta] = useState(null);
730
+ const [page, setPage] = useState(1);
611
731
 
612
732
  useEffect(() => {
613
- client.boards.listPosts(boardSlug)
614
- .then(res => setPosts(res.data))
615
- .finally(() => setLoading(false));
616
- }, [boardSlug]);
617
-
618
- if (loading) return <div>Loading...</div>;
733
+ client.blog.list({ page, per_page: 10 })
734
+ .then(({ data, meta }) => {
735
+ setPosts(data); // Always an array
736
+ setMeta(meta);
737
+ });
738
+ }, [page]);
619
739
 
620
740
  return (
621
- <table>
622
- <thead>
623
- <tr>
624
- <th>제목</th>
625
- <th>작성자</th>
626
- <th>조회수</th>
627
- <th>작성일</th>
628
- </tr>
629
- </thead>
630
- <tbody>
631
- {posts.map(post => (
632
- <tr key={post.id}>
633
- <td>{post.title}</td>
634
- <td>{post.author}</td>
635
- <td>{post.views}</td>
636
- <td>{new Date(post.created_at).toLocaleDateString()}</td>
637
- </tr>
638
- ))}
639
- </tbody>
640
- </table>
641
- );
642
- }
643
-
644
- // 로그인 폼
645
- function LoginForm() {
646
- const [email, setEmail] = useState('');
647
- const [password, setPassword] = useState('');
648
- const [error, setError] = useState('');
649
-
650
- const handleSubmit = async (e) => {
651
- e.preventDefault();
652
- try {
653
- await client.auth.login({ email, password });
654
- // 로그인 성공 - 리다이렉트 등
655
- } catch (err) {
656
- setError(err.message);
657
- }
658
- };
741
+ <div>
742
+ {posts.map(post => (
743
+ <article key={post.id}>
744
+ <h2>{post.title}</h2>
745
+ <p>{post.excerpt}</p>
746
+ </article>
747
+ ))}
659
748
 
660
- return (
661
- <form onSubmit={handleSubmit}>
662
- <input
663
- type="email"
664
- value={email}
665
- onChange={e => setEmail(e.target.value)}
666
- placeholder="이메일"
667
- />
668
- <input
669
- type="password"
670
- value={password}
671
- onChange={e => setPassword(e.target.value)}
672
- placeholder="비밀번호"
673
- />
674
- {error && <p style={{color: 'red'}}>{error}</p>}
675
- <button type="submit">로그인</button>
676
- </form>
749
+ {meta && (
750
+ <div>
751
+ Page {meta.current_page} of {meta.last_page}
752
+ <button
753
+ onClick={() => setPage(p => p - 1)}
754
+ disabled={page <= 1}
755
+ >
756
+ Previous
757
+ </button>
758
+ <button
759
+ onClick={() => setPage(p => p + 1)}
760
+ disabled={page >= meta.last_page}
761
+ >
762
+ Next
763
+ </button>
764
+ </div>
765
+ )}
766
+ </div>
677
767
  );
678
768
  }
679
769
 
680
- // 상품 목록
681
- function ProductList() {
682
- const [products, setProducts] = useState([]);
770
+ // 예약
771
+ function ReservationForm() {
772
+ const [services, setServices] = useState([]);
773
+ const [selectedService, setSelectedService] = useState(null);
774
+ const [dates, setDates] = useState([]);
775
+ const [slots, setSlots] = useState([]);
683
776
 
684
777
  useEffect(() => {
685
- client.shop.listProducts({ is_featured: true })
686
- .then(res => setProducts(res.data));
778
+ client.reservation.listServices().then(setServices);
687
779
  }, []);
688
780
 
781
+ useEffect(() => {
782
+ if (selectedService) {
783
+ client.reservation.getAvailableDates({
784
+ service_id: selectedService,
785
+ }).then(setDates);
786
+ }
787
+ }, [selectedService]);
788
+
789
+ const handleDateSelect = async (date) => {
790
+ const availableSlots = await client.reservation.getAvailableSlots({
791
+ service_id: selectedService,
792
+ date,
793
+ });
794
+ setSlots(availableSlots);
795
+ };
796
+
689
797
  return (
690
- <div className="grid grid-cols-4 gap-4">
691
- {products.map(product => (
692
- <div key={product.id} className="border p-4">
693
- <img src={product.thumbnail} alt={product.name} />
694
- <h3>{product.name}</h3>
695
- <p>{product.price.toLocaleString()}원</p>
696
- {product.compare_price && (
697
- <p className="line-through">{product.compare_price.toLocaleString()}원</p>
698
- )}
699
- </div>
700
- ))}
798
+ <div>
799
+ <select onChange={e => setSelectedService(Number(e.target.value))}>
800
+ <option>서비스 선택</option>
801
+ {services.map(s => (
802
+ <option key={s.id} value={s.id}>{s.name}</option>
803
+ ))}
804
+ </select>
805
+
806
+ <div>
807
+ {dates.map(date => (
808
+ <button key={date} onClick={() => handleDateSelect(date)}>
809
+ {date}
810
+ </button>
811
+ ))}
812
+ </div>
813
+
814
+ <div>
815
+ {slots.filter(s => s.available).map(slot => (
816
+ <button key={slot.time}>{slot.time}</button>
817
+ ))}
818
+ </div>
701
819
  </div>
702
820
  );
703
821
  }
package/dist/index.d.mts CHANGED
@@ -620,6 +620,110 @@ interface UpdateEntityRecordData {
620
620
  status?: 'active' | 'archived' | 'draft';
621
621
  }
622
622
 
623
+ /**
624
+ * Reservation types for Promptly SDK
625
+ */
626
+ interface ReservationService {
627
+ id: number;
628
+ name: string;
629
+ slug: string;
630
+ description: string | null;
631
+ thumbnail: string | null;
632
+ duration: number;
633
+ price: number;
634
+ requires_staff: boolean;
635
+ requires_payment: boolean;
636
+ deposit: number;
637
+ staffs: ReservationStaffSummary[];
638
+ }
639
+ interface ReservationStaff {
640
+ id: number;
641
+ name: string;
642
+ avatar: string | null;
643
+ bio: string | null;
644
+ }
645
+ interface ReservationStaffSummary {
646
+ id: number;
647
+ name: string;
648
+ avatar: string | null;
649
+ }
650
+ interface ReservationSlot {
651
+ time: string;
652
+ available: boolean;
653
+ staff_id?: number;
654
+ }
655
+ interface ReservationSettings {
656
+ timezone: string;
657
+ slot_interval: number;
658
+ min_notice_hours: number;
659
+ max_advance_days: number;
660
+ cancellation_hours: number;
661
+ allow_online_payment: boolean;
662
+ bookable_date_range: {
663
+ start: string;
664
+ end: string;
665
+ };
666
+ }
667
+ interface Reservation {
668
+ id: number;
669
+ reservation_number: string;
670
+ status: 'pending' | 'confirmed' | 'completed' | 'cancelled' | 'no_show';
671
+ status_label: string;
672
+ reservation_date: string;
673
+ start_time: string;
674
+ end_time: string;
675
+ time_range: string;
676
+ customer_name: string;
677
+ customer_phone: string | null;
678
+ customer_email: string | null;
679
+ price: number;
680
+ deposit: number;
681
+ payment_status: 'pending' | 'paid' | 'refunded' | 'partial';
682
+ payment_status_label: string;
683
+ customer_memo: string | null;
684
+ can_cancel: boolean;
685
+ service: {
686
+ id: number;
687
+ name: string;
688
+ duration: number;
689
+ } | null;
690
+ staff: ReservationStaffSummary | null;
691
+ created_at: string;
692
+ }
693
+ interface CreateReservationData {
694
+ service_id: number;
695
+ staff_id?: number;
696
+ reservation_date: string;
697
+ start_time: string;
698
+ customer_name: string;
699
+ customer_phone?: string;
700
+ customer_email?: string;
701
+ customer_memo?: string;
702
+ }
703
+ interface CreateReservationResult {
704
+ reservation: Reservation;
705
+ requires_payment: boolean;
706
+ deposit: number;
707
+ }
708
+ interface AvailableDatesParams {
709
+ service_id: number;
710
+ staff_id?: number;
711
+ start_date?: string;
712
+ end_date?: string;
713
+ }
714
+ interface AvailableSlotsParams {
715
+ service_id: number;
716
+ date: string;
717
+ staff_id?: number;
718
+ }
719
+ interface ReservationListParams {
720
+ status?: string;
721
+ upcoming?: boolean;
722
+ past?: boolean;
723
+ per_page?: number;
724
+ page?: number;
725
+ }
726
+
623
727
  /**
624
728
  * HTTP Client for Promptly SDK
625
729
  */
@@ -1181,6 +1285,71 @@ declare class EntitiesResource {
1181
1285
  };
1182
1286
  }
1183
1287
 
1288
+ /**
1289
+ * Reservation Resource for Promptly SDK
1290
+ */
1291
+
1292
+ declare class ReservationResource {
1293
+ private http;
1294
+ constructor(http: HttpClient);
1295
+ /**
1296
+ * Get reservation settings
1297
+ * @returns Reservation settings for the tenant
1298
+ */
1299
+ getSettings(): Promise<ReservationSettings>;
1300
+ /**
1301
+ * List available services
1302
+ * @returns Array of services (always an array)
1303
+ */
1304
+ listServices(): Promise<ReservationService[]>;
1305
+ /**
1306
+ * List available staff members
1307
+ * @param serviceId - Optional: filter staff by service
1308
+ * @returns Array of staff members (always an array)
1309
+ */
1310
+ listStaff(serviceId?: number): Promise<ReservationStaff[]>;
1311
+ /**
1312
+ * Get available dates for booking
1313
+ * @returns Array of available date strings (YYYY-MM-DD)
1314
+ */
1315
+ getAvailableDates(params: AvailableDatesParams): Promise<string[]>;
1316
+ /**
1317
+ * Get available time slots for a specific date
1318
+ * @returns Array of available slots (always an array)
1319
+ */
1320
+ getAvailableSlots(params: AvailableSlotsParams): Promise<ReservationSlot[]>;
1321
+ /**
1322
+ * Create a new reservation
1323
+ * @returns Created reservation with payment info
1324
+ */
1325
+ create(data: CreateReservationData): Promise<CreateReservationResult>;
1326
+ /**
1327
+ * List my reservations
1328
+ * @returns ListResponse with reservations and pagination meta
1329
+ */
1330
+ list(params?: ReservationListParams): Promise<ListResponse<Reservation>>;
1331
+ /**
1332
+ * Get upcoming reservations
1333
+ * @returns Array of upcoming reservations
1334
+ */
1335
+ upcoming(limit?: number): Promise<Reservation[]>;
1336
+ /**
1337
+ * Get past reservations
1338
+ * @returns Array of past reservations
1339
+ */
1340
+ past(limit?: number): Promise<Reservation[]>;
1341
+ /**
1342
+ * Get reservation by reservation number
1343
+ */
1344
+ get(reservationNumber: string): Promise<Reservation>;
1345
+ /**
1346
+ * Cancel a reservation
1347
+ * @param reservationNumber - Reservation number to cancel
1348
+ * @param reason - Optional cancellation reason
1349
+ */
1350
+ cancel(reservationNumber: string, reason?: string): Promise<Reservation>;
1351
+ }
1352
+
1184
1353
  /**
1185
1354
  * Promptly SDK
1186
1355
  *
@@ -1223,6 +1392,8 @@ declare class Promptly {
1223
1392
  readonly media: MediaResource;
1224
1393
  /** Custom entities - dynamic data structures created by AI */
1225
1394
  readonly entities: EntitiesResource;
1395
+ /** Reservations - booking services and time slots */
1396
+ readonly reservation: ReservationResource;
1226
1397
  constructor(config: PromptlyConfig);
1227
1398
  /**
1228
1399
  * Get site theme settings
@@ -1250,4 +1421,4 @@ declare class Promptly {
1250
1421
  getToken(): string | null;
1251
1422
  }
1252
1423
 
1253
- export { type AddToCartData, type ApiError, type ApiResponse, type ApplyCouponData, type AuthResponse, type BlogListParams, type BlogPost, type Board, type BoardComment, type BoardListParams, type BoardPost, type BoardSettings, type Cart, type CartItem, type Coupon, type CouponType, type CouponValidation, type CreateCommentData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CustomEntity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormField, type FormFieldOption, type FormFieldType, type FormFieldValidation, type FormListParams, type FormSettings, type FormSubmission, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type Order, type OrderItem, type OrderListParams, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PostListParams, type Product, type ProductCategory, type ProductListParams, type ProductOption, type ProductOptionValue, type ProductStatus, type ProductVariant, Promptly, type PromptlyConfig, PromptlyError, type RegisterData, type ResetPasswordData, type SocialAuthUrl, type SocialProvider, type SubmissionListParams, type SubmitFormData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProfileData, Promptly as default };
1424
+ export { type AddToCartData, type ApiError, type ApiResponse, type ApplyCouponData, type AuthResponse, type AvailableDatesParams, type AvailableSlotsParams, type BlogListParams, type BlogPost, type Board, type BoardComment, type BoardListParams, type BoardPost, type BoardSettings, type Cart, type CartItem, type Coupon, type CouponType, type CouponValidation, type CreateCommentData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CreateReservationData, type CreateReservationResult, type CustomEntity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormField, type FormFieldOption, type FormFieldType, type FormFieldValidation, type FormListParams, type FormSettings, type FormSubmission, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type Order, type OrderItem, type OrderListParams, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PostListParams, type Product, type ProductCategory, type ProductListParams, type ProductOption, type ProductOptionValue, type ProductStatus, type ProductVariant, Promptly, type PromptlyConfig, PromptlyError, type RegisterData, type Reservation, type ReservationListParams, type ReservationService, type ReservationSettings, type ReservationSlot, type ReservationStaff, type ReservationStaffSummary, type ResetPasswordData, type SocialAuthUrl, type SocialProvider, type SubmissionListParams, type SubmitFormData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProfileData, Promptly as default };
package/dist/index.d.ts CHANGED
@@ -620,6 +620,110 @@ interface UpdateEntityRecordData {
620
620
  status?: 'active' | 'archived' | 'draft';
621
621
  }
622
622
 
623
+ /**
624
+ * Reservation types for Promptly SDK
625
+ */
626
+ interface ReservationService {
627
+ id: number;
628
+ name: string;
629
+ slug: string;
630
+ description: string | null;
631
+ thumbnail: string | null;
632
+ duration: number;
633
+ price: number;
634
+ requires_staff: boolean;
635
+ requires_payment: boolean;
636
+ deposit: number;
637
+ staffs: ReservationStaffSummary[];
638
+ }
639
+ interface ReservationStaff {
640
+ id: number;
641
+ name: string;
642
+ avatar: string | null;
643
+ bio: string | null;
644
+ }
645
+ interface ReservationStaffSummary {
646
+ id: number;
647
+ name: string;
648
+ avatar: string | null;
649
+ }
650
+ interface ReservationSlot {
651
+ time: string;
652
+ available: boolean;
653
+ staff_id?: number;
654
+ }
655
+ interface ReservationSettings {
656
+ timezone: string;
657
+ slot_interval: number;
658
+ min_notice_hours: number;
659
+ max_advance_days: number;
660
+ cancellation_hours: number;
661
+ allow_online_payment: boolean;
662
+ bookable_date_range: {
663
+ start: string;
664
+ end: string;
665
+ };
666
+ }
667
+ interface Reservation {
668
+ id: number;
669
+ reservation_number: string;
670
+ status: 'pending' | 'confirmed' | 'completed' | 'cancelled' | 'no_show';
671
+ status_label: string;
672
+ reservation_date: string;
673
+ start_time: string;
674
+ end_time: string;
675
+ time_range: string;
676
+ customer_name: string;
677
+ customer_phone: string | null;
678
+ customer_email: string | null;
679
+ price: number;
680
+ deposit: number;
681
+ payment_status: 'pending' | 'paid' | 'refunded' | 'partial';
682
+ payment_status_label: string;
683
+ customer_memo: string | null;
684
+ can_cancel: boolean;
685
+ service: {
686
+ id: number;
687
+ name: string;
688
+ duration: number;
689
+ } | null;
690
+ staff: ReservationStaffSummary | null;
691
+ created_at: string;
692
+ }
693
+ interface CreateReservationData {
694
+ service_id: number;
695
+ staff_id?: number;
696
+ reservation_date: string;
697
+ start_time: string;
698
+ customer_name: string;
699
+ customer_phone?: string;
700
+ customer_email?: string;
701
+ customer_memo?: string;
702
+ }
703
+ interface CreateReservationResult {
704
+ reservation: Reservation;
705
+ requires_payment: boolean;
706
+ deposit: number;
707
+ }
708
+ interface AvailableDatesParams {
709
+ service_id: number;
710
+ staff_id?: number;
711
+ start_date?: string;
712
+ end_date?: string;
713
+ }
714
+ interface AvailableSlotsParams {
715
+ service_id: number;
716
+ date: string;
717
+ staff_id?: number;
718
+ }
719
+ interface ReservationListParams {
720
+ status?: string;
721
+ upcoming?: boolean;
722
+ past?: boolean;
723
+ per_page?: number;
724
+ page?: number;
725
+ }
726
+
623
727
  /**
624
728
  * HTTP Client for Promptly SDK
625
729
  */
@@ -1181,6 +1285,71 @@ declare class EntitiesResource {
1181
1285
  };
1182
1286
  }
1183
1287
 
1288
+ /**
1289
+ * Reservation Resource for Promptly SDK
1290
+ */
1291
+
1292
+ declare class ReservationResource {
1293
+ private http;
1294
+ constructor(http: HttpClient);
1295
+ /**
1296
+ * Get reservation settings
1297
+ * @returns Reservation settings for the tenant
1298
+ */
1299
+ getSettings(): Promise<ReservationSettings>;
1300
+ /**
1301
+ * List available services
1302
+ * @returns Array of services (always an array)
1303
+ */
1304
+ listServices(): Promise<ReservationService[]>;
1305
+ /**
1306
+ * List available staff members
1307
+ * @param serviceId - Optional: filter staff by service
1308
+ * @returns Array of staff members (always an array)
1309
+ */
1310
+ listStaff(serviceId?: number): Promise<ReservationStaff[]>;
1311
+ /**
1312
+ * Get available dates for booking
1313
+ * @returns Array of available date strings (YYYY-MM-DD)
1314
+ */
1315
+ getAvailableDates(params: AvailableDatesParams): Promise<string[]>;
1316
+ /**
1317
+ * Get available time slots for a specific date
1318
+ * @returns Array of available slots (always an array)
1319
+ */
1320
+ getAvailableSlots(params: AvailableSlotsParams): Promise<ReservationSlot[]>;
1321
+ /**
1322
+ * Create a new reservation
1323
+ * @returns Created reservation with payment info
1324
+ */
1325
+ create(data: CreateReservationData): Promise<CreateReservationResult>;
1326
+ /**
1327
+ * List my reservations
1328
+ * @returns ListResponse with reservations and pagination meta
1329
+ */
1330
+ list(params?: ReservationListParams): Promise<ListResponse<Reservation>>;
1331
+ /**
1332
+ * Get upcoming reservations
1333
+ * @returns Array of upcoming reservations
1334
+ */
1335
+ upcoming(limit?: number): Promise<Reservation[]>;
1336
+ /**
1337
+ * Get past reservations
1338
+ * @returns Array of past reservations
1339
+ */
1340
+ past(limit?: number): Promise<Reservation[]>;
1341
+ /**
1342
+ * Get reservation by reservation number
1343
+ */
1344
+ get(reservationNumber: string): Promise<Reservation>;
1345
+ /**
1346
+ * Cancel a reservation
1347
+ * @param reservationNumber - Reservation number to cancel
1348
+ * @param reason - Optional cancellation reason
1349
+ */
1350
+ cancel(reservationNumber: string, reason?: string): Promise<Reservation>;
1351
+ }
1352
+
1184
1353
  /**
1185
1354
  * Promptly SDK
1186
1355
  *
@@ -1223,6 +1392,8 @@ declare class Promptly {
1223
1392
  readonly media: MediaResource;
1224
1393
  /** Custom entities - dynamic data structures created by AI */
1225
1394
  readonly entities: EntitiesResource;
1395
+ /** Reservations - booking services and time slots */
1396
+ readonly reservation: ReservationResource;
1226
1397
  constructor(config: PromptlyConfig);
1227
1398
  /**
1228
1399
  * Get site theme settings
@@ -1250,4 +1421,4 @@ declare class Promptly {
1250
1421
  getToken(): string | null;
1251
1422
  }
1252
1423
 
1253
- export { type AddToCartData, type ApiError, type ApiResponse, type ApplyCouponData, type AuthResponse, type BlogListParams, type BlogPost, type Board, type BoardComment, type BoardListParams, type BoardPost, type BoardSettings, type Cart, type CartItem, type Coupon, type CouponType, type CouponValidation, type CreateCommentData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CustomEntity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormField, type FormFieldOption, type FormFieldType, type FormFieldValidation, type FormListParams, type FormSettings, type FormSubmission, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type Order, type OrderItem, type OrderListParams, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PostListParams, type Product, type ProductCategory, type ProductListParams, type ProductOption, type ProductOptionValue, type ProductStatus, type ProductVariant, Promptly, type PromptlyConfig, PromptlyError, type RegisterData, type ResetPasswordData, type SocialAuthUrl, type SocialProvider, type SubmissionListParams, type SubmitFormData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProfileData, Promptly as default };
1424
+ export { type AddToCartData, type ApiError, type ApiResponse, type ApplyCouponData, type AuthResponse, type AvailableDatesParams, type AvailableSlotsParams, type BlogListParams, type BlogPost, type Board, type BoardComment, type BoardListParams, type BoardPost, type BoardSettings, type Cart, type CartItem, type Coupon, type CouponType, type CouponValidation, type CreateCommentData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CreateReservationData, type CreateReservationResult, type CustomEntity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormField, type FormFieldOption, type FormFieldType, type FormFieldValidation, type FormListParams, type FormSettings, type FormSubmission, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type Order, type OrderItem, type OrderListParams, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PostListParams, type Product, type ProductCategory, type ProductListParams, type ProductOption, type ProductOptionValue, type ProductStatus, type ProductVariant, Promptly, type PromptlyConfig, PromptlyError, type RegisterData, type Reservation, type ReservationListParams, type ReservationService, type ReservationSettings, type ReservationSlot, type ReservationStaff, type ReservationStaffSummary, type ResetPasswordData, type SocialAuthUrl, type SocialProvider, type SubmissionListParams, type SubmitFormData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProfileData, Promptly as default };
package/dist/index.js CHANGED
@@ -958,6 +958,110 @@ var EntitiesResource = class {
958
958
  }
959
959
  };
960
960
 
961
+ // src/resources/reservation.ts
962
+ var ReservationResource = class {
963
+ constructor(http) {
964
+ this.http = http;
965
+ }
966
+ // ============================================
967
+ // Public Endpoints
968
+ // ============================================
969
+ /**
970
+ * Get reservation settings
971
+ * @returns Reservation settings for the tenant
972
+ */
973
+ async getSettings() {
974
+ return this.http.get("/public/reservations/settings");
975
+ }
976
+ /**
977
+ * List available services
978
+ * @returns Array of services (always an array)
979
+ */
980
+ async listServices() {
981
+ const response = await this.http.getList("/public/reservations/services");
982
+ return response.data;
983
+ }
984
+ /**
985
+ * List available staff members
986
+ * @param serviceId - Optional: filter staff by service
987
+ * @returns Array of staff members (always an array)
988
+ */
989
+ async listStaff(serviceId) {
990
+ const params = serviceId ? { service_id: serviceId } : void 0;
991
+ const response = await this.http.getList("/public/reservations/staffs", params);
992
+ return response.data;
993
+ }
994
+ /**
995
+ * Get available dates for booking
996
+ * @returns Array of available date strings (YYYY-MM-DD)
997
+ */
998
+ async getAvailableDates(params) {
999
+ const response = await this.http.get("/public/reservations/dates", params);
1000
+ return Array.isArray(response) ? response : response?.data ?? [];
1001
+ }
1002
+ /**
1003
+ * Get available time slots for a specific date
1004
+ * @returns Array of available slots (always an array)
1005
+ */
1006
+ async getAvailableSlots(params) {
1007
+ const response = await this.http.get("/public/reservations/slots", params);
1008
+ return Array.isArray(response) ? response : response?.data ?? [];
1009
+ }
1010
+ // ============================================
1011
+ // Protected Endpoints (requires auth)
1012
+ // ============================================
1013
+ /**
1014
+ * Create a new reservation
1015
+ * @returns Created reservation with payment info
1016
+ */
1017
+ async create(data) {
1018
+ return this.http.post("/reservations", data);
1019
+ }
1020
+ /**
1021
+ * List my reservations
1022
+ * @returns ListResponse with reservations and pagination meta
1023
+ */
1024
+ async list(params) {
1025
+ return this.http.getList("/reservations", params);
1026
+ }
1027
+ /**
1028
+ * Get upcoming reservations
1029
+ * @returns Array of upcoming reservations
1030
+ */
1031
+ async upcoming(limit = 10) {
1032
+ const response = await this.http.getList("/reservations", {
1033
+ upcoming: true,
1034
+ per_page: limit
1035
+ });
1036
+ return response.data;
1037
+ }
1038
+ /**
1039
+ * Get past reservations
1040
+ * @returns Array of past reservations
1041
+ */
1042
+ async past(limit = 10) {
1043
+ const response = await this.http.getList("/reservations", {
1044
+ past: true,
1045
+ per_page: limit
1046
+ });
1047
+ return response.data;
1048
+ }
1049
+ /**
1050
+ * Get reservation by reservation number
1051
+ */
1052
+ async get(reservationNumber) {
1053
+ return this.http.get(`/reservations/${reservationNumber}`);
1054
+ }
1055
+ /**
1056
+ * Cancel a reservation
1057
+ * @param reservationNumber - Reservation number to cancel
1058
+ * @param reason - Optional cancellation reason
1059
+ */
1060
+ async cancel(reservationNumber, reason) {
1061
+ return this.http.post(`/reservations/${reservationNumber}/cancel`, { reason });
1062
+ }
1063
+ };
1064
+
961
1065
  // src/index.ts
962
1066
  var Promptly = class {
963
1067
  constructor(config) {
@@ -969,6 +1073,7 @@ var Promptly = class {
969
1073
  this.shop = new ShopResource(this.http);
970
1074
  this.media = new MediaResource(this.http);
971
1075
  this.entities = new EntitiesResource(this.http);
1076
+ this.reservation = new ReservationResource(this.http);
972
1077
  }
973
1078
  /**
974
1079
  * Get site theme settings
package/dist/index.mjs CHANGED
@@ -930,6 +930,110 @@ var EntitiesResource = class {
930
930
  }
931
931
  };
932
932
 
933
+ // src/resources/reservation.ts
934
+ var ReservationResource = class {
935
+ constructor(http) {
936
+ this.http = http;
937
+ }
938
+ // ============================================
939
+ // Public Endpoints
940
+ // ============================================
941
+ /**
942
+ * Get reservation settings
943
+ * @returns Reservation settings for the tenant
944
+ */
945
+ async getSettings() {
946
+ return this.http.get("/public/reservations/settings");
947
+ }
948
+ /**
949
+ * List available services
950
+ * @returns Array of services (always an array)
951
+ */
952
+ async listServices() {
953
+ const response = await this.http.getList("/public/reservations/services");
954
+ return response.data;
955
+ }
956
+ /**
957
+ * List available staff members
958
+ * @param serviceId - Optional: filter staff by service
959
+ * @returns Array of staff members (always an array)
960
+ */
961
+ async listStaff(serviceId) {
962
+ const params = serviceId ? { service_id: serviceId } : void 0;
963
+ const response = await this.http.getList("/public/reservations/staffs", params);
964
+ return response.data;
965
+ }
966
+ /**
967
+ * Get available dates for booking
968
+ * @returns Array of available date strings (YYYY-MM-DD)
969
+ */
970
+ async getAvailableDates(params) {
971
+ const response = await this.http.get("/public/reservations/dates", params);
972
+ return Array.isArray(response) ? response : response?.data ?? [];
973
+ }
974
+ /**
975
+ * Get available time slots for a specific date
976
+ * @returns Array of available slots (always an array)
977
+ */
978
+ async getAvailableSlots(params) {
979
+ const response = await this.http.get("/public/reservations/slots", params);
980
+ return Array.isArray(response) ? response : response?.data ?? [];
981
+ }
982
+ // ============================================
983
+ // Protected Endpoints (requires auth)
984
+ // ============================================
985
+ /**
986
+ * Create a new reservation
987
+ * @returns Created reservation with payment info
988
+ */
989
+ async create(data) {
990
+ return this.http.post("/reservations", data);
991
+ }
992
+ /**
993
+ * List my reservations
994
+ * @returns ListResponse with reservations and pagination meta
995
+ */
996
+ async list(params) {
997
+ return this.http.getList("/reservations", params);
998
+ }
999
+ /**
1000
+ * Get upcoming reservations
1001
+ * @returns Array of upcoming reservations
1002
+ */
1003
+ async upcoming(limit = 10) {
1004
+ const response = await this.http.getList("/reservations", {
1005
+ upcoming: true,
1006
+ per_page: limit
1007
+ });
1008
+ return response.data;
1009
+ }
1010
+ /**
1011
+ * Get past reservations
1012
+ * @returns Array of past reservations
1013
+ */
1014
+ async past(limit = 10) {
1015
+ const response = await this.http.getList("/reservations", {
1016
+ past: true,
1017
+ per_page: limit
1018
+ });
1019
+ return response.data;
1020
+ }
1021
+ /**
1022
+ * Get reservation by reservation number
1023
+ */
1024
+ async get(reservationNumber) {
1025
+ return this.http.get(`/reservations/${reservationNumber}`);
1026
+ }
1027
+ /**
1028
+ * Cancel a reservation
1029
+ * @param reservationNumber - Reservation number to cancel
1030
+ * @param reason - Optional cancellation reason
1031
+ */
1032
+ async cancel(reservationNumber, reason) {
1033
+ return this.http.post(`/reservations/${reservationNumber}/cancel`, { reason });
1034
+ }
1035
+ };
1036
+
933
1037
  // src/index.ts
934
1038
  var Promptly = class {
935
1039
  constructor(config) {
@@ -941,6 +1045,7 @@ var Promptly = class {
941
1045
  this.shop = new ShopResource(this.http);
942
1046
  this.media = new MediaResource(this.http);
943
1047
  this.entities = new EntitiesResource(this.http);
1048
+ this.reservation = new ReservationResource(this.http);
944
1049
  }
945
1050
  /**
946
1051
  * Get site theme settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@back23/promptly-sdk",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "Promptly AI CMS SDK for JavaScript/TypeScript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",