Skip to content

Commit 4ae0dff

Browse files
changing
1 parent d8ae7b5 commit 4ae0dff

39 files changed

Lines changed: 870 additions & 267 deletions

.agent/rules/backend-architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
trigger: model_decision
3-
description: ./apps/api/src/**/
3+
description: ./backend/src/**/
44
---
55

66
# 🏛️ Architectural Rules: Hexagonal Architecture (Medical Luxury API)

.agent/rules/frontend.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
trigger: model_decision
3-
description: ./apps/admin-panel/src/**/
3+
description: ./frontend/src/**/
44
globs: ./apps/admin-panel/src/**/
55
---
66

@@ -47,10 +47,10 @@ alwaysApply: true
4747
### Компонент с signals:
4848

4949
```typescript
50-
import { Component, signal, computed, input } from '@angular/core';
50+
import { Component, signal, computed, input } from "@angular/core";
5151

5252
@Component({
53-
selector: 'app-example',
53+
selector: "app-example",
5454
standalone: true,
5555
template: `
5656
<div>
@@ -62,7 +62,7 @@ import { Component, signal, computed, input } from '@angular/core';
6262
`,
6363
})
6464
export class ExampleComponent {
65-
title = input('Default Title');
65+
title = input("Default Title");
6666
count = signal(0);
6767

6868
doubleCount = computed(() => this.count() * 2);
@@ -76,10 +76,10 @@ export class ExampleComponent {
7676
### Сервис с signals:
7777

7878
```typescript
79-
import { Injectable, signal, computed } from '@angular/core';
79+
import { Injectable, signal, computed } from "@angular/core";
8080

8181
@Injectable({
82-
providedIn: 'root',
82+
providedIn: "root",
8383
})
8484
export class DataService {
8585
private data = signal<any[]>([]);
@@ -108,7 +108,7 @@ export class DataService {
108108
```typescript
109109
export class BadComponent {
110110
count = 0; // НЕ используйте обычные свойства
111-
title = 'Hello'; // НЕ используйте обычные свойства
111+
title = "Hello"; // НЕ используйте обычные свойства
112112

113113
increment() {
114114
this.count++; // Это не будет работать в zoneless режиме

.agent/workflows/aaa-architecture.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Эксперт по Full-Stack разработке: Angular 18+ (Signals/Zoneless/FSD) и NestJS (Модульная/Гексагональная архитектура) с использованием MongoDB.
2+
description: Эксперт по Full-Stack разработке: Angular 21+ (Signals/Zoneless/FSD) и NestJS (Модульная/Гексагональная архитектура) с использованием MongoDB.
33
---
44

55
---
@@ -32,6 +32,7 @@ You are the **Lead Architect and Product Strategist** for the 'Mavluda Beauty' e
3232
- **Change Detection**: **Zoneless** mode only. Use `provideZonelessChangeDetection()`.
3333
- **State**: Use **Angular Signals** (`signal`, `computed`, `effect`) for ALL reactivity.
3434
- **API**: Use FSD-based aliases (e.g., `@shared/api`, `@entities/booking`).
35+
- **Angular Forms** : Forms with signals
3536

3637
### Backend (NestJS + Hexagonal)
3738

.github/prompts/mavluda-beauty.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ mode: agent
1010

1111
# Master Workflow: aaa-architecture.md
1212

13-
Antigravity, you are now in "Full Reconstruction Mode". Your goal is to rewrite the entire project from scratch (apps/api and apps/admin-panel) to align with our new 2026 Luxury Standards.
13+
Antigravity, you are now in "Full Reconstruction Mode". Your goal is to rewrite the entire project from scratch (frontend and backend) to align with our new 2026 Luxury Standards.
1414

15-
### 1. PHASE ONE: FRONTEND REVOLUTION (apps/admin-panel)
15+
### 1. PHASE ONE: FRONTEND REVOLUTION (frontend)
1616

1717
- Implement Feature Sliced Design (FSD) structure: app, pages, features, widgets, entities, shared.
1818
- Transition ALL components to Standalone, Zoneless, and Signal-based architecture.
1919
- Remove all inline templates and styles. Every component MUST have separate .ts, .html, and .scss files.
2020
- Apply Flowbite + Tailwind CSS with the "Gold & Luxury" theme defined in frontend.md.
2121
- Ensure 100% type safety; eliminate 'any'.
2222

23-
### 2. PHASE TWO: BACKEND TRANSFORMATION (apps/api)
23+
### 2. PHASE TWO: BACKEND TRANSFORMATION (backend)
2424

2525
- Refactor the entire NestJS codebase into Hexagonal Architecture (Domain, Application, Infrastructure).
2626
- Ensure the Domain layer is pure and has zero external dependencies.
Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,43 @@
1-
name: Build NestJS API
1+
# name: Build NestJS API
22

3-
on:
4-
push:
5-
branches:
6-
- main
7-
paths:
8-
- "backend/**"
3+
# on:
4+
# push:
5+
# branches:
6+
# - main
7+
# paths:
8+
# - "backend/**"
99

10-
jobs:
11-
build-backend:
12-
runs-on: ubuntu-latest
13-
timeout-minutes: 10 # Защита от бесконечного зависания
10+
# jobs:
11+
# build-backend:
12+
# runs-on: ubuntu-latest
13+
# timeout-minutes: 10 # Защита от бесконечного зависания
1414

15-
steps:
16-
- name: Checkout code
17-
uses: actions/checkout@v4.2.2
15+
# steps:
16+
# - name: Checkout code
17+
# uses: actions/checkout@v4.2.2
1818

19-
# 1. Настраиваем Node.js и кеширование для npm
20-
- name: Setup Node.js
21-
uses: actions/setup-node@v4.1.0
22-
with:
23-
node-version: "20"
24-
cache: "npm" # Теперь используем только кеш npm
19+
# # 1. Настраиваем Node.js и кеширование для npm
20+
# - name: Setup Node.js
21+
# uses: actions/setup-node@v4.1.0
22+
# with:
23+
# node-version: "20"
24+
# cache: "npm" # Теперь используем только кеш npm
2525

26-
# 2. Устанавливаем зависимости
27-
# Используем npm ci для максимальной стабильности в CI/CD
28-
# Флаг --legacy-peer-deps нужен для корректной работы Nx и зависимостей Angular/NestJS
29-
- name: Install dependencies
30-
run: npm ci --legacy-peer-deps
26+
# # 2. Устанавливаем зависимости
27+
# # Используем npm ci для максимальной стабильности в CI/CD
28+
# # Флаг --legacy-peer-deps нужен для корректной работы Nx и зависимостей Angular/NestJS
29+
# - name: Install dependencies
30+
# run: npm ci --legacy-peer-deps
3131

32-
# 3. Сборка через Nx
33-
- name: Build NestJS
34-
run: npx nx build api --prod
32+
# # 3. Сборка через Nx
33+
# - name: Build NestJS
34+
# run: npx nx build api --prod
3535

36-
# 4. Деплой билда в ветку gh-backend
37-
- name: Deploy Build to gh-backend branch
38-
uses: JamesIves/github-pages-deploy-action@v4.7.2
39-
with:
40-
folder: dist/apps/api
41-
branch: gh-backend
42-
token: ${{ secrets.GITHUB_TOKEN }}
43-
clean: true
36+
# # 4. Деплой билда в ветку gh-backend
37+
# - name: Deploy Build to gh-backend branch
38+
# uses: JamesIves/github-pages-deploy-action@v4.7.2
39+
# with:
40+
# folder: dist/apps/api
41+
# branch: gh-backend
42+
# token: ${{ secrets.GITHUB_TOKEN }}
43+
# clean: true

backend/src/app.module.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import { ServiceModule } from './service/service.module';
1212
import { GalleryModule } from './gallery/gallery.module';
1313
import { AuthModule } from './auth/auth.module';
1414
import { PaymentModule } from './payment/payment.module';
15+
import { BookingModule } from './booking/booking.module';
16+
import { InventoryModule } from './inventory/inventory.module';
17+
import { PartnershipModule } from './partnership/partnership.module';
1518

1619
@Module({
1720
imports: [
@@ -24,6 +27,9 @@ import { PaymentModule } from './payment/payment.module';
2427
GalleryModule,
2528
AuthModule,
2629
PaymentModule,
30+
BookingModule,
31+
InventoryModule,
32+
PartnershipModule,
2733
ServeStaticModule.forRoot({
2834
rootPath: join(__dirname, '..', 'uploads'),
2935
serveRoot: '/uploads',
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { Booking } from '../domain/booking.entity';
3+
import { BookingRepository } from '../infrastructure/repositories/booking.repository';
4+
import { CreateBookingDto } from '../presentation/dto/create-booking.dto';
5+
import { UpdateBookingDto } from '../presentation/dto/update-booking.dto';
6+
7+
@Injectable()
8+
export class BookingService {
9+
constructor(private readonly bookingRepository: BookingRepository) {}
10+
11+
async findAll(): Promise<Booking[]> {
12+
return this.bookingRepository.findAll();
13+
}
14+
15+
async create(createBookingDto: CreateBookingDto): Promise<Booking> {
16+
return this.bookingRepository.create({
17+
...createBookingDto,
18+
status: 'pending',
19+
});
20+
}
21+
22+
async findOne(id: string): Promise<Booking> {
23+
const booking = await this.bookingRepository.findById(id);
24+
if (!booking) {
25+
throw new Error(`Booking with ID ${id} not found`);
26+
}
27+
return booking;
28+
}
29+
30+
async update(id: string, updateBookingDto: UpdateBookingDto): Promise<Booking> {
31+
const updated = await this.bookingRepository.update(id, updateBookingDto);
32+
if (!updated) {
33+
throw new Error(`Booking with ID ${id} not found`);
34+
}
35+
return updated;
36+
}
37+
38+
async remove(id: string): Promise<void> {
39+
const deleted = await this.bookingRepository.delete(id);
40+
if (!deleted) {
41+
throw new Error(`Booking with ID ${id} not found`);
42+
}
43+
}
44+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Module } from '@nestjs/common';
2+
import { MongooseModule } from '@nestjs/mongoose';
3+
import { BookingService } from './application/booking.service';
4+
import { BookingController } from './presentation/booking.controller';
5+
import { BookingRepository } from './infrastructure/repositories/booking.repository';
6+
import { BookingSchema, BookingSchemaEntity } from './infrastructure/schemas/booking.schema';
7+
8+
@Module({
9+
imports: [
10+
MongooseModule.forFeature([
11+
{ name: BookingSchemaEntity.name, schema: BookingSchema },
12+
]),
13+
],
14+
controllers: [BookingController],
15+
providers: [BookingService, BookingRepository],
16+
exports: [BookingService],
17+
})
18+
export class BookingModule {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export class Booking {
2+
constructor(
3+
public readonly id: string,
4+
public readonly customerName: string,
5+
public readonly date: Date,
6+
public readonly status: 'pending' | 'confirmed' | 'cancelled',
7+
public readonly createdAt: Date,
8+
public readonly updatedAt: Date,
9+
) {}
10+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { InjectModel } from '@nestjs/mongoose';
3+
import { Model } from 'mongoose';
4+
import { Booking } from '../../domain/booking.entity';
5+
import { BookingDocument, BookingSchemaEntity } from '../schemas/booking.schema';
6+
7+
@Injectable()
8+
export class BookingRepository {
9+
constructor(
10+
@InjectModel(BookingSchemaEntity.name)
11+
private readonly bookingModel: Model<BookingDocument>,
12+
) {}
13+
14+
async findAll(): Promise<Booking[]> {
15+
const docs = await this.bookingModel.find().exec();
16+
return docs.map((doc) => this.toDomain(doc));
17+
}
18+
19+
async create(booking: Omit<Booking, 'id' | 'createdAt' | 'updatedAt'>): Promise<Booking> {
20+
const created = new this.bookingModel(booking);
21+
const doc = await created.save();
22+
return this.toDomain(doc);
23+
}
24+
25+
async findById(id: string): Promise<Booking | null> {
26+
if (!id || !id.match(/^[0-9a-fA-F]{24}$/)) {
27+
return null;
28+
}
29+
const doc = await this.bookingModel.findById(id).exec();
30+
return doc ? this.toDomain(doc) : null;
31+
}
32+
33+
async update(id: string, updateData: Partial<Booking>): Promise<Booking | null> {
34+
const doc = await this.bookingModel
35+
.findByIdAndUpdate(id, { $set: updateData }, { new: true })
36+
.exec();
37+
return doc ? this.toDomain(doc) : null;
38+
}
39+
40+
async delete(id: string): Promise<boolean> {
41+
const result = await this.bookingModel.findByIdAndDelete(id).exec();
42+
return !!result;
43+
}
44+
45+
private toDomain(doc: BookingDocument): Booking {
46+
const d = doc as any;
47+
return new Booking(
48+
d._id.toString(),
49+
d.customerName,
50+
d.date,
51+
d.status,
52+
d.createdAt,
53+
d.updatedAt
54+
);
55+
}
56+
}

0 commit comments

Comments
 (0)