Merge pull request #236 from Tria-plc/freight/feature/vehicle_2

Freight/feature/vehicle 2
This commit is contained in:
marshal
2026-06-22 15:49:06 +03:00
committed by GitHub
228 changed files with 14263 additions and 223 deletions

View File

@@ -63,6 +63,9 @@ import { WarehousesModule } from './modules/warehouses/warehouses.module';
import { FacilitiesModule } from './modules/facilities/facilities.module';
import { OverviewModule } from './modules/overview/overview.module';
import { VehiclesModule } from './modules/vehicles/vehicles.module';
import { DriversModule } from './modules/drivers/drivers.module';
import { FirstMileModule } from './modules/first-mile/first-mile.module';
import { LastMileModule } from './modules/last-mile/last-mile.module';
@Module({
imports: [
@@ -122,6 +125,9 @@ import { VehiclesModule } from './modules/vehicles/vehicles.module';
WarehousesModule,
OverviewModule,
VehiclesModule,
DriversModule,
FirstMileModule,
LastMileModule,
],
providers: [
EdrOrgSeeder,

View File

@@ -0,0 +1,42 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class CreateDriversTable1775000000000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'drivers' AND table_schema = 'freight') THEN
CREATE TABLE freight.drivers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
license_number VARCHAR NOT NULL UNIQUE,
first_name VARCHAR NOT NULL,
last_name VARCHAR NOT NULL,
email VARCHAR NOT NULL UNIQUE,
phone_number VARCHAR NOT NULL UNIQUE,
date_of_birth DATE NOT NULL,
license_expiry_date DATE NOT NULL,
status VARCHAR DEFAULT 'ACTIVE' NOT NULL,
vehicle_types_authorized VARCHAR[],
address TEXT,
emergency_contact VARCHAR,
notes TEXT,
total_trips INTEGER DEFAULT 0,
rating NUMERIC(3, 2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
deleted_at TIMESTAMP NULL
);
CREATE INDEX idx_drivers_license_number ON freight.drivers(license_number);
CREATE INDEX idx_drivers_email ON freight.drivers(email);
CREATE INDEX idx_drivers_phone_number ON freight.drivers(phone_number);
CREATE INDEX idx_drivers_status ON freight.drivers(status);
END IF;
END $$;
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE IF EXISTS freight.drivers CASCADE;`);
}
}

View File

@@ -0,0 +1,50 @@
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm';
/**
* Add driver assignment fields to vehicles table
*/
export class AddVehicleDriverAssignment1800000000001 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const vehiclesTable = await queryRunner.getTable('freight.vehicles');
if (vehiclesTable) {
const hasAssignedDriverId = vehiclesTable.columns.some((col) => col.name === 'assigned_driver_id');
if (!hasAssignedDriverId) {
await queryRunner.addColumn(
'freight.vehicles',
new TableColumn({
name: 'assigned_driver_id',
type: 'uuid',
isNullable: true,
}),
);
}
const hasAssignedDriverName = vehiclesTable.columns.some((col) => col.name === 'assigned_driver_name');
if (!hasAssignedDriverName) {
await queryRunner.addColumn(
'freight.vehicles',
new TableColumn({
name: 'assigned_driver_name',
type: 'varchar',
isNullable: true,
}),
);
}
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
const vehiclesTable = await queryRunner.getTable('freight.vehicles');
if (vehiclesTable) {
const hasAssignedDriverId = vehiclesTable.columns.some((col) => col.name === 'assigned_driver_id');
if (hasAssignedDriverId) {
await queryRunner.dropColumn('freight.vehicles', 'assigned_driver_id');
}
const hasAssignedDriverName = vehiclesTable.columns.some((col) => col.name === 'assigned_driver_name');
if (hasAssignedDriverName) {
await queryRunner.dropColumn('freight.vehicles', 'assigned_driver_name');
}
}
}
}

View File

@@ -0,0 +1,106 @@
import { MigrationInterface, QueryRunner, Table, TableForeignKey } from 'typeorm';
/**
* Create the freight.first_mile table — one row per booking's first-mile
* (door → terminal) leg, with payment split and an optional assigned vehicle.
*/
export class CreateFirstMile1810000000000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const exists = await queryRunner.hasTable('freight.first_mile');
if (exists) return;
await queryRunner.createTable(
new Table({
name: 'freight.first_mile',
columns: [
{
name: 'id',
type: 'uuid',
isPrimary: true,
default: 'gen_random_uuid()',
},
{ name: 'booking_id', type: 'uuid', isNullable: false },
{
name: 'status',
type: 'varchar',
length: '30',
default: `'PAYMENT_PENDING'`,
isNullable: false,
},
{
name: 'advanced_payment',
type: 'numeric',
precision: 14,
scale: 2,
default: 0,
isNullable: false,
},
{
name: 'remaining_payment',
type: 'numeric',
precision: 14,
scale: 2,
default: 0,
isNullable: false,
},
{
name: 'estimated_km',
type: 'numeric',
precision: 10,
scale: 2,
isNullable: true,
},
{
name: 'exact_km',
type: 'numeric',
precision: 10,
scale: 2,
isNullable: true,
},
{ name: 'vehicle_id', type: 'uuid', isNullable: true },
{ name: 'created_at', type: 'timestamptz', default: 'now()' },
{ name: 'updated_at', type: 'timestamptz', default: 'now()' },
{ name: 'deleted_at', type: 'timestamptz', isNullable: true },
],
}),
true,
);
await queryRunner.createForeignKey(
'freight.first_mile',
new TableForeignKey({
columnNames: ['booking_id'],
referencedTableName: 'freight.bookings',
referencedColumnNames: ['id'],
onDelete: 'CASCADE',
}),
);
await queryRunner.createForeignKey(
'freight.first_mile',
new TableForeignKey({
columnNames: ['vehicle_id'],
referencedTableName: 'freight.vehicles',
referencedColumnNames: ['id'],
onDelete: 'SET NULL',
}),
);
await queryRunner.query(
`CREATE INDEX "IDX_first_mile_booking_id" ON "freight"."first_mile" ("booking_id")`,
);
await queryRunner.query(
`CREATE INDEX "IDX_first_mile_status" ON "freight"."first_mile" ("status")`,
);
await queryRunner.query(
`CREATE INDEX "IDX_first_mile_vehicle_id" ON "freight"."first_mile" ("vehicle_id")`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
const exists = await queryRunner.hasTable('freight.first_mile');
if (exists) {
await queryRunner.dropTable('freight.first_mile');
}
}
}

View File

@@ -0,0 +1,106 @@
import { MigrationInterface, QueryRunner, Table, TableForeignKey } from 'typeorm';
/**
* Create the freight.last_mile table — one row per booking's last-mile
* (terminal → door) leg, with payment split and an optional assigned vehicle.
*/
export class CreateLastMile1810000000001 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const exists = await queryRunner.hasTable('freight.last_mile');
if (exists) return;
await queryRunner.createTable(
new Table({
name: 'freight.last_mile',
columns: [
{
name: 'id',
type: 'uuid',
isPrimary: true,
default: 'gen_random_uuid()',
},
{ name: 'booking_id', type: 'uuid', isNullable: false },
{
name: 'status',
type: 'varchar',
length: '30',
default: `'PAYMENT_PENDING'`,
isNullable: false,
},
{
name: 'advanced_payment',
type: 'numeric',
precision: 14,
scale: 2,
default: 0,
isNullable: false,
},
{
name: 'remaining_payment',
type: 'numeric',
precision: 14,
scale: 2,
default: 0,
isNullable: false,
},
{
name: 'estimated_km',
type: 'numeric',
precision: 10,
scale: 2,
isNullable: true,
},
{
name: 'exact_km',
type: 'numeric',
precision: 10,
scale: 2,
isNullable: true,
},
{ name: 'vehicle_id', type: 'uuid', isNullable: true },
{ name: 'created_at', type: 'timestamptz', default: 'now()' },
{ name: 'updated_at', type: 'timestamptz', default: 'now()' },
{ name: 'deleted_at', type: 'timestamptz', isNullable: true },
],
}),
true,
);
await queryRunner.createForeignKey(
'freight.last_mile',
new TableForeignKey({
columnNames: ['booking_id'],
referencedTableName: 'freight.bookings',
referencedColumnNames: ['id'],
onDelete: 'CASCADE',
}),
);
await queryRunner.createForeignKey(
'freight.last_mile',
new TableForeignKey({
columnNames: ['vehicle_id'],
referencedTableName: 'freight.vehicles',
referencedColumnNames: ['id'],
onDelete: 'SET NULL',
}),
);
await queryRunner.query(
`CREATE INDEX "IDX_last_mile_booking_id" ON "freight"."last_mile" ("booking_id")`,
);
await queryRunner.query(
`CREATE INDEX "IDX_last_mile_status" ON "freight"."last_mile" ("status")`,
);
await queryRunner.query(
`CREATE INDEX "IDX_last_mile_vehicle_id" ON "freight"."last_mile" ("vehicle_id")`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
const exists = await queryRunner.hasTable('freight.last_mile');
if (exists) {
await queryRunner.dropTable('freight.last_mile');
}
}
}

View File

@@ -0,0 +1,74 @@
import {
Controller,
Get,
Post,
Patch,
Delete,
Param,
Body,
Query,
ParseUUIDPipe,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { FleetManage, FleetView } from '../../common/booking-guards';
import { DriversService } from './drivers.service';
import { CreateDriverDto } from './dto/create-driver.dto';
import { UpdateDriverDto } from './dto/update-driver.dto';
@ApiTags('drivers')
@ApiBearerAuth()
@Controller('drivers')
@FleetView()
export class DriversController {
constructor(private readonly driversService: DriversService) {}
@Post()
@FleetManage()
@ApiOperation({ summary: 'Create a new driver' })
create(@Body() createDriverDto: CreateDriverDto) {
return this.driversService.create(createDriverDto);
}
@Get()
@ApiOperation({ summary: 'Get all drivers with filters' })
findAll(
@Query('search') search?: string,
@Query('status') status?: string,
@Query('page') page?: string,
@Query('limit') limit?: string,
@Query('sortBy') sortBy?: string,
@Query('sortOrder') sortOrder?: 'ASC' | 'DESC',
) {
return this.driversService.findAll({
search,
status: status as any,
page: page ? parseInt(page) : undefined,
limit: limit ? parseInt(limit) : undefined,
sortBy,
sortOrder,
});
}
@Get(':id')
@ApiOperation({ summary: 'Get driver by id' })
findOne(@Param('id', ParseUUIDPipe) id: string) {
return this.driversService.findById(id);
}
@Patch(':id')
@FleetManage()
@ApiOperation({ summary: 'Update a driver' })
update(
@Param('id', ParseUUIDPipe) id: string,
@Body() updateDriverDto: UpdateDriverDto,
) {
return this.driversService.update(id, updateDriverDto);
}
@Delete(':id')
@FleetManage()
@ApiOperation({ summary: 'Delete a driver' })
remove(@Param('id', ParseUUIDPipe) id: string) {
return this.driversService.remove(id);
}
}

View File

@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Driver } from './entities/driver.entity';
import { DriversService } from './drivers.service';
import { DriversController } from './drivers.controller';
@Module({
imports: [TypeOrmModule.forFeature([Driver])],
providers: [DriversService],
controllers: [DriversController],
exports: [DriversService],
})
export class DriversModule {}

View File

@@ -0,0 +1,88 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BaseRepository } from '@edr/api-common';
import { Driver } from './entities/driver.entity';
@Injectable()
export class DriversRepository extends BaseRepository<Driver> {
constructor(
@InjectRepository(Driver)
repository: Repository<Driver>,
) {
super(repository);
}
async findByLicenseNumber(licenseNumber: string): Promise<Driver | null> {
return this.repository.findOne({ where: { licenseNumber } });
}
async findByEmail(email: string): Promise<Driver | null> {
return this.repository.findOne({ where: { email } });
}
async findByPhoneNumber(phoneNumber: string): Promise<Driver | null> {
return this.repository.findOne({ where: { phoneNumber } });
}
async findDriverById(id: string): Promise<Driver | null> {
return this.repository.findOne({ where: { id } });
}
async findAllWithFilters(query: {
page?: number;
pageSize?: number;
search?: string;
status?: string;
sortBy?: string;
sortOrder?: 'ASC' | 'DESC';
}) {
const page = query.page || 1;
const pageSize = query.pageSize || 10;
const skip = (page - 1) * pageSize;
let queryBuilder = this.repository.createQueryBuilder('driver');
if (query.search) {
queryBuilder = queryBuilder.where(
'(driver.firstName ILIKE :search OR driver.lastName ILIKE :search OR driver.email ILIKE :search OR driver.phoneNumber ILIKE :search OR driver.licenseNumber ILIKE :search)',
{ search: `%${query.search}%` },
);
}
if (query.status) {
queryBuilder = queryBuilder.andWhere('driver.status = :status', {
status: query.status,
});
}
const sortBy = query.sortBy || 'createdAt';
const sortOrder = query.sortOrder || 'DESC';
queryBuilder = queryBuilder
.orderBy(`driver.${sortBy}`, sortOrder)
.skip(skip)
.take(pageSize);
const [data, total] = await queryBuilder.getManyAndCount();
return {
data,
total,
page,
pageSize,
totalPages: Math.ceil(total / pageSize),
};
}
async createDriver(driverData: any): Promise<Driver> {
const driver = this.repository.create(driverData);
const result = await this.repository.save(driver);
return result?.[0] as Driver;
}
async updateDriver(driver: Driver): Promise<Driver> {
const result = await this.repository.save(driver);
return result as Driver;
}
}

View File

@@ -0,0 +1,119 @@
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateDriverDto } from './dto/create-driver.dto';
import { UpdateDriverDto } from './dto/update-driver.dto';
import { Driver, DriverStatus } from './entities/driver.entity';
@Injectable()
export class DriversService {
constructor(
@InjectRepository(Driver)
private readonly driverRepo: Repository<Driver>,
) {}
async create(dto: CreateDriverDto): Promise<Driver> {
const existing = await this.driverRepo.findOne({
where: [
{ licenseNumber: dto.licenseNumber },
{ email: dto.email },
{ phoneNumber: dto.phoneNumber },
],
});
if (existing) {
if (existing.licenseNumber === dto.licenseNumber) {
throw new ConflictException(`Driver with license number ${dto.licenseNumber} already exists`);
}
if (existing.email === dto.email) {
throw new ConflictException(`Driver with email ${dto.email} already exists`);
}
if (existing.phoneNumber === dto.phoneNumber) {
throw new ConflictException(`Driver with phone number ${dto.phoneNumber} already exists`);
}
}
const driver = this.driverRepo.create(dto);
return this.driverRepo.save(driver);
}
async findAll(query: {
search?: string;
status?: DriverStatus | string;
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'ASC' | 'DESC';
} = {}): Promise<Driver[]> {
const qb = this.driverRepo.createQueryBuilder('d');
if (query.search) {
const searchTerm = `%${query.search}%`;
qb.where('d.firstName ILIKE :search', { search: searchTerm })
.orWhere('d.lastName ILIKE :search', { search: searchTerm })
.orWhere('d.email ILIKE :search', { search: searchTerm })
.orWhere('d.licenseNumber ILIKE :search', { search: searchTerm })
.orWhere('d.phoneNumber ILIKE :search', { search: searchTerm });
}
if (query.status) {
qb.andWhere('d.status = :status', { status: query.status });
}
const sortBy = query.sortBy && ['firstName', 'lastName', 'status', 'createdAt'].includes(query.sortBy)
? query.sortBy
: 'createdAt';
const sortOrder = (query.sortOrder ?? 'DESC').toUpperCase();
return qb
.orderBy(`d.${sortBy}`, sortOrder as 'ASC' | 'DESC')
.getMany();
}
async findById(id: string): Promise<Driver> {
const driver = await this.driverRepo.findOne({ where: { id } });
if (!driver) {
throw new NotFoundException(`Driver ${id} not found`);
}
return driver;
}
async update(id: string, dto: UpdateDriverDto): Promise<Driver> {
const driver = await this.findById(id);
if (dto.licenseNumber && dto.licenseNumber !== driver.licenseNumber) {
const existing = await this.driverRepo.findOne({
where: { licenseNumber: dto.licenseNumber },
});
if (existing) {
throw new ConflictException(`Driver with license number ${dto.licenseNumber} already exists`);
}
}
if (dto.email && dto.email !== driver.email) {
const existing = await this.driverRepo.findOne({
where: { email: dto.email },
});
if (existing) {
throw new ConflictException(`Driver with email ${dto.email} already exists`);
}
}
if (dto.phoneNumber && dto.phoneNumber !== driver.phoneNumber) {
const existing = await this.driverRepo.findOne({
where: { phoneNumber: dto.phoneNumber },
});
if (existing) {
throw new ConflictException(`Driver with phone number ${dto.phoneNumber} already exists`);
}
}
Object.assign(driver, dto);
return this.driverRepo.save(driver);
}
async remove(id: string): Promise<void> {
await this.findById(id);
await this.driverRepo.softDelete(id);
}
}

View File

@@ -0,0 +1,45 @@
import { IsString, IsEmail, IsDateString, IsEnum, IsOptional, IsArray } from 'class-validator';
import { DriverStatus } from '../entities/driver.entity';
export class CreateDriverDto {
@IsString()
licenseNumber!: string;
@IsString()
firstName!: string;
@IsString()
lastName!: string;
@IsEmail()
email!: string;
@IsString()
phoneNumber!: string;
@IsDateString()
dateOfBirth!: string;
@IsDateString()
licenseExpiryDate!: string;
@IsEnum(DriverStatus)
status!: DriverStatus;
@IsOptional()
@IsArray()
@IsString({ each: true })
vehicleTypesAuthorized?: string[];
@IsOptional()
@IsString()
address?: string;
@IsOptional()
@IsString()
emergencyContact?: string;
@IsOptional()
@IsString()
notes?: string;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateDriverDto } from './create-driver.dto';
export class UpdateDriverDto extends PartialType(CreateDriverDto) {}

View File

@@ -0,0 +1,54 @@
import { Entity, Column } from 'typeorm';
import { BaseEntity } from '@edr/api-common';
export enum DriverStatus {
ACTIVE = 'ACTIVE',
INACTIVE = 'INACTIVE',
SUSPENDED = 'SUSPENDED',
ON_LEAVE = 'ON_LEAVE',
}
@Entity({ name: 'drivers', schema: 'freight' })
export class Driver extends BaseEntity {
@Column({ name: 'license_number', unique: true, nullable: true })
licenseNumber?: string;
@Column({ name: 'first_name', nullable: true })
firstName?: string;
@Column({ name: 'last_name', nullable: true })
lastName?: string;
@Column({ unique: true, nullable: true })
email?: string;
@Column({ name: 'phone_number', unique: true, nullable: true })
phoneNumber?: string;
@Column({ name: 'date_of_birth', type: 'date', nullable: true })
dateOfBirth?: Date;
@Column({ name: 'license_expiry_date', type: 'date', nullable: true })
licenseExpiryDate?: Date;
@Column({ type: 'varchar', default: DriverStatus.ACTIVE, nullable: true })
status?: DriverStatus;
@Column({ name: 'vehicle_types_authorized', type: 'varchar', array: true, nullable: true })
vehicleTypesAuthorized?: string[];
@Column({ type: 'text', nullable: true })
address?: string | null;
@Column({ name: 'emergency_contact', type: 'varchar', nullable: true })
emergencyContact?: string | null;
@Column({ type: 'text', nullable: true })
notes?: string | null;
@Column({ name: 'total_trips', type: 'int', default: 0, nullable: true })
totalTrips?: number;
@Column({ type: 'numeric', precision: 3, scale: 2, nullable: true })
rating?: number | null;
}

View File

@@ -0,0 +1,60 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsIn, IsNumber, IsOptional, IsUUID, Min } from 'class-validator';
import { FIRST_MILE_STATUSES, FirstMileStatus } from '../entities/first-mile.entity';
const toNumber = ({ value }: { value: unknown }) =>
value === '' || value == null ? undefined : Number(value);
export class CreateFirstMileDto {
@ApiProperty({ description: 'Booking this first-mile leg belongs to (FK → bookings.id)' })
@IsUUID()
bookingId!: string;
@ApiPropertyOptional({
enum: FIRST_MILE_STATUSES,
default: 'PAYMENT_PENDING',
})
@IsOptional()
@IsIn(FIRST_MILE_STATUSES as unknown as string[])
status?: FirstMileStatus;
@ApiPropertyOptional({ description: 'Amount already paid in advance', example: 4200 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
advancedPayment?: number;
@ApiPropertyOptional({ description: 'Outstanding balance to be collected', example: 1800 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
remainingPayment?: number;
@ApiPropertyOptional({ description: 'Planned distance for the leg, in km', example: 42.5 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
estimatedKm?: number;
@ApiPropertyOptional({ description: 'Actual distance travelled, in km', example: 44.1 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
exactKm?: number;
@ApiPropertyOptional({
type: String,
format: 'uuid',
description: 'Assigned vehicle (FK → vehicles.id). May be null until assigned.',
nullable: true,
})
@IsOptional()
@IsUUID()
vehicleId?: string | null;
}

View File

@@ -0,0 +1,5 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateFirstMileDto } from './create-first-mile.dto';
export class UpdateFirstMileDto extends PartialType(CreateFirstMileDto) {}

View File

@@ -0,0 +1,49 @@
import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
import { Booking } from '../../bookings/entities/booking.entity';
import { Vehicle } from '../../vehicles/entities/vehicle.entity';
export const FIRST_MILE_STATUSES = [
'PAYMENT_PENDING',
'READY_TO_TRANSIT',
'IN_TRANSIT',
'RECEIVED_TO_PORT',
] as const;
export type FirstMileStatus = (typeof FIRST_MILE_STATUSES)[number];
@Entity({ name: 'first_mile', schema: 'freight' })
@Index(['bookingId'])
@Index(['status'])
@Index(['vehicleId'])
export class FirstMile extends BaseEntity {
@Column({ name: 'booking_id', type: 'uuid' })
bookingId!: string;
@ManyToOne(() => Booking, { nullable: false, eager: false })
@JoinColumn({ name: 'booking_id' })
booking?: Booking;
@Column({ name: 'status', type: 'varchar', length: 30, default: 'PAYMENT_PENDING' })
status!: FirstMileStatus;
@Column({ name: 'advanced_payment', type: 'numeric', precision: 14, scale: 2, default: 0 })
advancedPayment!: number;
@Column({ name: 'remaining_payment', type: 'numeric', precision: 14, scale: 2, default: 0 })
remainingPayment!: number;
@Column({ name: 'estimated_km', type: 'numeric', precision: 10, scale: 2, nullable: true })
estimatedKm?: number | null;
@Column({ name: 'exact_km', type: 'numeric', precision: 10, scale: 2, nullable: true })
exactKm?: number | null;
@Column({ name: 'vehicle_id', type: 'uuid', nullable: true })
vehicleId?: string | null;
@ManyToOne(() => Vehicle, { nullable: true, eager: false })
@JoinColumn({ name: 'vehicle_id' })
vehicle?: Vehicle | null;
}

View File

@@ -0,0 +1,79 @@
import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Param,
ParseUUIDPipe,
Patch,
Post,
Query,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { TrainSchedulingManage, TrainSchedulingView } from '../../common/booking-guards';
import { CreateFirstMileDto } from './dto/create-first-mile.dto';
import { UpdateFirstMileDto } from './dto/update-first-mile.dto';
import { FirstMileStatus } from './entities/first-mile.entity';
import { FirstMileService } from './first-mile.service';
@ApiTags('first-mile')
@ApiBearerAuth()
@Controller('first-mile')
@TrainSchedulingView()
export class FirstMileController {
constructor(private readonly firstMileService: FirstMileService) {}
@Get()
@ApiOperation({ summary: 'List first-mile legs' })
findAll(
@Query('status') status?: string,
@Query('bookingId') bookingId?: string,
@Query('vehicleId') vehicleId?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
@Query('sortBy') sortBy?: string,
@Query('sortOrder') sortOrder?: 'ASC' | 'DESC',
) {
return this.firstMileService.findAll({
status: status as FirstMileStatus | undefined,
bookingId,
vehicleId,
page: page ? parseInt(page, 10) : undefined,
pageSize: pageSize ? parseInt(pageSize, 10) : undefined,
sortBy,
sortOrder,
});
}
@Get(':id')
@ApiOperation({ summary: 'Get a first-mile leg by ID' })
findOne(@Param('id', ParseUUIDPipe) id: string) {
return this.firstMileService.findById(id);
}
@Post()
@TrainSchedulingManage()
@ApiOperation({ summary: 'Create a first-mile leg' })
create(@Body() dto: CreateFirstMileDto) {
return this.firstMileService.create(dto);
}
@Patch(':id')
@TrainSchedulingManage()
@ApiOperation({ summary: 'Update a first-mile leg' })
update(@Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateFirstMileDto) {
return this.firstMileService.update(id, dto);
}
@Delete(':id')
@TrainSchedulingManage()
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Soft-delete a first-mile leg' })
remove(@Param('id', ParseUUIDPipe) id: string) {
return this.firstMileService.remove(id);
}
}

View File

@@ -0,0 +1,15 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FirstMile } from './entities/first-mile.entity';
import { FirstMileController } from './first-mile.controller';
import { FirstMileRepository } from './first-mile.repository';
import { FirstMileService } from './first-mile.service';
@Module({
imports: [TypeOrmModule.forFeature([FirstMile])],
controllers: [FirstMileController],
providers: [FirstMileRepository, FirstMileService],
exports: [FirstMileRepository, FirstMileService],
})
export class FirstMileModule {}

View File

@@ -0,0 +1,16 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BaseRepository } from '@edr/api-common';
import { FirstMile } from './entities/first-mile.entity';
@Injectable()
export class FirstMileRepository extends BaseRepository<FirstMile> {
constructor(
@InjectRepository(FirstMile)
repository: Repository<FirstMile>,
) {
super(repository);
}
}

View File

@@ -0,0 +1,113 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { FindOptionsWhere } from 'typeorm';
import { CreateFirstMileDto } from './dto/create-first-mile.dto';
import { UpdateFirstMileDto } from './dto/update-first-mile.dto';
import { FirstMile, FirstMileStatus } from './entities/first-mile.entity';
import { FirstMileRepository } from './first-mile.repository';
type FirstMileListFilter = {
status?: FirstMileStatus;
bookingId?: string;
vehicleId?: string;
page?: number;
pageSize?: number;
sortBy?: string;
sortOrder?: string;
};
const SORTABLE_FIELDS: (keyof FirstMile)[] = [
'status',
'advancedPayment',
'remainingPayment',
'createdAt',
];
@Injectable()
export class FirstMileService {
constructor(private readonly firstMileRepository: FirstMileRepository) {}
async findAll(filter: FirstMileListFilter = {}): Promise<{
data: FirstMile[];
meta: { total: number; page: number; pageSize: number; totalPages: number };
}> {
const page = filter.page ?? 1;
const pageSize = filter.pageSize ?? 50;
const sortBy = SORTABLE_FIELDS.includes(filter.sortBy as keyof FirstMile)
? (filter.sortBy as keyof FirstMile)
: 'createdAt';
const sortOrder = filter.sortOrder?.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
const where: FindOptionsWhere<FirstMile> = {};
if (filter.status) where.status = filter.status;
if (filter.bookingId) where.bookingId = filter.bookingId;
if (filter.vehicleId) where.vehicleId = filter.vehicleId;
const [data, total] = await this.firstMileRepository.findAndCount({
where,
relations: { booking: true, vehicle: true },
order: { [sortBy]: sortOrder },
skip: (page - 1) * pageSize,
take: pageSize,
});
return {
data,
meta: {
total,
page,
pageSize,
totalPages: Math.max(1, Math.ceil(total / pageSize)),
},
};
}
async findById(id: string): Promise<FirstMile> {
const record = await this.firstMileRepository.findById(id, {
relations: { booking: true, vehicle: true },
});
if (!record) {
throw new NotFoundException(`First-mile record ${id} not found`);
}
return record;
}
async create(dto: CreateFirstMileDto): Promise<FirstMile> {
return this.firstMileRepository.create({
bookingId: dto.bookingId,
status: dto.status ?? 'PAYMENT_PENDING',
advancedPayment: dto.advancedPayment ?? 0,
remainingPayment: dto.remainingPayment ?? 0,
estimatedKm: dto.estimatedKm ?? null,
exactKm: dto.exactKm ?? null,
vehicleId: dto.vehicleId ?? null,
});
}
async update(id: string, dto: UpdateFirstMileDto): Promise<FirstMile> {
await this.findById(id);
const updated = await this.firstMileRepository.update(id, {
...(dto.bookingId !== undefined ? { bookingId: dto.bookingId } : {}),
...(dto.status !== undefined ? { status: dto.status } : {}),
...(dto.advancedPayment !== undefined ? { advancedPayment: dto.advancedPayment } : {}),
...(dto.remainingPayment !== undefined ? { remainingPayment: dto.remainingPayment } : {}),
...(dto.estimatedKm !== undefined ? { estimatedKm: dto.estimatedKm } : {}),
...(dto.exactKm !== undefined ? { exactKm: dto.exactKm } : {}),
...(dto.vehicleId !== undefined ? { vehicleId: dto.vehicleId } : {}),
});
if (!updated) {
throw new NotFoundException(`First-mile record ${id} not found`);
}
return updated;
}
async remove(id: string): Promise<void> {
await this.findById(id);
await this.firstMileRepository.softDelete(id);
}
}

View File

@@ -0,0 +1,60 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsIn, IsNumber, IsOptional, IsUUID, Min } from 'class-validator';
import { LAST_MILE_STATUSES, LastMileStatus } from '../entities/last-mile.entity';
const toNumber = ({ value }: { value: unknown }) =>
value === '' || value == null ? undefined : Number(value);
export class CreateLastMileDto {
@ApiProperty({ description: 'Booking this last-mile leg belongs to (FK → bookings.id)' })
@IsUUID()
bookingId!: string;
@ApiPropertyOptional({
enum: LAST_MILE_STATUSES,
default: 'PAYMENT_PENDING',
})
@IsOptional()
@IsIn(LAST_MILE_STATUSES as unknown as string[])
status?: LastMileStatus;
@ApiPropertyOptional({ description: 'Amount already paid in advance', example: 4200 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
advancedPayment?: number;
@ApiPropertyOptional({ description: 'Outstanding balance to be collected', example: 1800 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
remainingPayment?: number;
@ApiPropertyOptional({ description: 'Planned distance for the leg, in km', example: 42.5 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
estimatedKm?: number;
@ApiPropertyOptional({ description: 'Actual distance travelled, in km', example: 44.1 })
@IsOptional()
@Transform(toNumber)
@IsNumber()
@Min(0)
exactKm?: number;
@ApiPropertyOptional({
type: String,
format: 'uuid',
description: 'Assigned vehicle (FK → vehicles.id). May be null until assigned.',
nullable: true,
})
@IsOptional()
@IsUUID()
vehicleId?: string | null;
}

View File

@@ -0,0 +1,5 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateLastMileDto } from './create-last-mile.dto';
export class UpdateLastMileDto extends PartialType(CreateLastMileDto) {}

View File

@@ -0,0 +1,49 @@
import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
import { Booking } from '../../bookings/entities/booking.entity';
import { Vehicle } from '../../vehicles/entities/vehicle.entity';
export const LAST_MILE_STATUSES = [
'PAYMENT_PENDING',
'READY_TO_TRANSIT',
'IN_TRANSIT',
'DELIVERED',
] as const;
export type LastMileStatus = (typeof LAST_MILE_STATUSES)[number];
@Entity({ name: 'last_mile', schema: 'freight' })
@Index(['bookingId'])
@Index(['status'])
@Index(['vehicleId'])
export class LastMile extends BaseEntity {
@Column({ name: 'booking_id', type: 'uuid' })
bookingId!: string;
@ManyToOne(() => Booking, { nullable: false, eager: false })
@JoinColumn({ name: 'booking_id' })
booking?: Booking;
@Column({ name: 'status', type: 'varchar', length: 30, default: 'PAYMENT_PENDING' })
status!: LastMileStatus;
@Column({ name: 'advanced_payment', type: 'numeric', precision: 14, scale: 2, default: 0 })
advancedPayment!: number;
@Column({ name: 'remaining_payment', type: 'numeric', precision: 14, scale: 2, default: 0 })
remainingPayment!: number;
@Column({ name: 'estimated_km', type: 'numeric', precision: 10, scale: 2, nullable: true })
estimatedKm?: number | null;
@Column({ name: 'exact_km', type: 'numeric', precision: 10, scale: 2, nullable: true })
exactKm?: number | null;
@Column({ name: 'vehicle_id', type: 'uuid', nullable: true })
vehicleId?: string | null;
@ManyToOne(() => Vehicle, { nullable: true, eager: false })
@JoinColumn({ name: 'vehicle_id' })
vehicle?: Vehicle | null;
}

View File

@@ -0,0 +1,79 @@
import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Param,
ParseUUIDPipe,
Patch,
Post,
Query,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { TrainSchedulingManage, TrainSchedulingView } from '../../common/booking-guards';
import { CreateLastMileDto } from './dto/create-last-mile.dto';
import { UpdateLastMileDto } from './dto/update-last-mile.dto';
import { LastMileStatus } from './entities/last-mile.entity';
import { LastMileService } from './last-mile.service';
@ApiTags('last-mile')
@ApiBearerAuth()
@Controller('last-mile')
@TrainSchedulingView()
export class LastMileController {
constructor(private readonly lastMileService: LastMileService) {}
@Get()
@ApiOperation({ summary: 'List last-mile legs' })
findAll(
@Query('status') status?: string,
@Query('bookingId') bookingId?: string,
@Query('vehicleId') vehicleId?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
@Query('sortBy') sortBy?: string,
@Query('sortOrder') sortOrder?: 'ASC' | 'DESC',
) {
return this.lastMileService.findAll({
status: status as LastMileStatus | undefined,
bookingId,
vehicleId,
page: page ? parseInt(page, 10) : undefined,
pageSize: pageSize ? parseInt(pageSize, 10) : undefined,
sortBy,
sortOrder,
});
}
@Get(':id')
@ApiOperation({ summary: 'Get a last-mile leg by ID' })
findOne(@Param('id', ParseUUIDPipe) id: string) {
return this.lastMileService.findById(id);
}
@Post()
@TrainSchedulingManage()
@ApiOperation({ summary: 'Create a last-mile leg' })
create(@Body() dto: CreateLastMileDto) {
return this.lastMileService.create(dto);
}
@Patch(':id')
@TrainSchedulingManage()
@ApiOperation({ summary: 'Update a last-mile leg' })
update(@Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateLastMileDto) {
return this.lastMileService.update(id, dto);
}
@Delete(':id')
@TrainSchedulingManage()
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Soft-delete a last-mile leg' })
remove(@Param('id', ParseUUIDPipe) id: string) {
return this.lastMileService.remove(id);
}
}

View File

@@ -0,0 +1,15 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { LastMile } from './entities/last-mile.entity';
import { LastMileController } from './last-mile.controller';
import { LastMileRepository } from './last-mile.repository';
import { LastMileService } from './last-mile.service';
@Module({
imports: [TypeOrmModule.forFeature([LastMile])],
controllers: [LastMileController],
providers: [LastMileRepository, LastMileService],
exports: [LastMileRepository, LastMileService],
})
export class LastMileModule {}

View File

@@ -0,0 +1,16 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BaseRepository } from '@edr/api-common';
import { LastMile } from './entities/last-mile.entity';
@Injectable()
export class LastMileRepository extends BaseRepository<LastMile> {
constructor(
@InjectRepository(LastMile)
repository: Repository<LastMile>,
) {
super(repository);
}
}

View File

@@ -0,0 +1,113 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { FindOptionsWhere } from 'typeorm';
import { CreateLastMileDto } from './dto/create-last-mile.dto';
import { UpdateLastMileDto } from './dto/update-last-mile.dto';
import { LastMile, LastMileStatus } from './entities/last-mile.entity';
import { LastMileRepository } from './last-mile.repository';
type LastMileListFilter = {
status?: LastMileStatus;
bookingId?: string;
vehicleId?: string;
page?: number;
pageSize?: number;
sortBy?: string;
sortOrder?: string;
};
const SORTABLE_FIELDS: (keyof LastMile)[] = [
'status',
'advancedPayment',
'remainingPayment',
'createdAt',
];
@Injectable()
export class LastMileService {
constructor(private readonly lastMileRepository: LastMileRepository) {}
async findAll(filter: LastMileListFilter = {}): Promise<{
data: LastMile[];
meta: { total: number; page: number; pageSize: number; totalPages: number };
}> {
const page = filter.page ?? 1;
const pageSize = filter.pageSize ?? 50;
const sortBy = SORTABLE_FIELDS.includes(filter.sortBy as keyof LastMile)
? (filter.sortBy as keyof LastMile)
: 'createdAt';
const sortOrder = filter.sortOrder?.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
const where: FindOptionsWhere<LastMile> = {};
if (filter.status) where.status = filter.status;
if (filter.bookingId) where.bookingId = filter.bookingId;
if (filter.vehicleId) where.vehicleId = filter.vehicleId;
const [data, total] = await this.lastMileRepository.findAndCount({
where,
relations: { booking: true, vehicle: true },
order: { [sortBy]: sortOrder },
skip: (page - 1) * pageSize,
take: pageSize,
});
return {
data,
meta: {
total,
page,
pageSize,
totalPages: Math.max(1, Math.ceil(total / pageSize)),
},
};
}
async findById(id: string): Promise<LastMile> {
const record = await this.lastMileRepository.findById(id, {
relations: { booking: true, vehicle: true },
});
if (!record) {
throw new NotFoundException(`Last-mile record ${id} not found`);
}
return record;
}
async create(dto: CreateLastMileDto): Promise<LastMile> {
return this.lastMileRepository.create({
bookingId: dto.bookingId,
status: dto.status ?? 'PAYMENT_PENDING',
advancedPayment: dto.advancedPayment ?? 0,
remainingPayment: dto.remainingPayment ?? 0,
estimatedKm: dto.estimatedKm ?? null,
exactKm: dto.exactKm ?? null,
vehicleId: dto.vehicleId ?? null,
});
}
async update(id: string, dto: UpdateLastMileDto): Promise<LastMile> {
await this.findById(id);
const updated = await this.lastMileRepository.update(id, {
...(dto.bookingId !== undefined ? { bookingId: dto.bookingId } : {}),
...(dto.status !== undefined ? { status: dto.status } : {}),
...(dto.advancedPayment !== undefined ? { advancedPayment: dto.advancedPayment } : {}),
...(dto.remainingPayment !== undefined ? { remainingPayment: dto.remainingPayment } : {}),
...(dto.estimatedKm !== undefined ? { estimatedKm: dto.estimatedKm } : {}),
...(dto.exactKm !== undefined ? { exactKm: dto.exactKm } : {}),
...(dto.vehicleId !== undefined ? { vehicleId: dto.vehicleId } : {}),
});
if (!updated) {
throw new NotFoundException(`Last-mile record ${id} not found`);
}
return updated;
}
async remove(id: string): Promise<void> {
await this.findById(id);
await this.lastMileRepository.softDelete(id);
}
}

View File

@@ -1,4 +1,4 @@
import { IsString, IsEnum, IsNumber, IsOptional } from 'class-validator';
import { IsString, IsEnum, IsNumber, IsOptional, IsUUID } from 'class-validator';
import { VehicleType, FuelType, VehicleStatus } from '../entities/vehicle.entity';
export class CreateVehicleDto {
@@ -29,4 +29,12 @@ export class CreateVehicleDto {
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsUUID()
assignedDriverId?: string;
@IsOptional()
@IsString()
assignedDriverName?: string;
}

View File

@@ -1,4 +1,4 @@
import { Entity, Column, Index } from 'typeorm';
import { Entity, Column } from 'typeorm';
import { BaseEntity } from '@edr/api-common';
export enum VehicleType {
@@ -26,39 +26,40 @@ export enum VehicleStatus {
}
@Entity({ name: 'vehicles', schema: 'freight' })
@Index(['plateNumber'])
@Index(['registrationNumber'])
@Index(['status'])
@Index(['vehicleType'])
@Index(['manufacturer'])
export class Vehicle extends BaseEntity {
@Column({ name: 'plate_number', unique: true })
plateNumber!: string;
@Column({ name: 'plate_number', unique: true, nullable: true })
plateNumber?: string;
@Column({ name: 'registration_number', unique: true })
registrationNumber!: string;
@Column({ name: 'registration_number', unique: true, nullable: true })
registrationNumber?: string;
@Column({ name: 'vehicle_type', type: 'varchar' })
vehicleType!: VehicleType;
@Column({ name: 'vehicle_type', type: 'varchar', nullable: true })
vehicleType?: VehicleType;
@Column()
manufacturer!: string;
@Column({ nullable: true })
manufacturer?: string;
@Column()
model!: string;
@Column({ nullable: true })
model?: string;
@Column()
year!: number;
@Column({ nullable: true })
year?: number;
@Column({ name: 'fuel_type', type: 'varchar' })
fuelType!: FuelType;
@Column({ name: 'fuel_type', type: 'varchar', nullable: true })
fuelType?: FuelType;
@Column()
capacity!: number;
@Column({ nullable: true })
capacity?: number;
@Column({ name: 'status', type: 'varchar', default: VehicleStatus.ACTIVE })
status!: VehicleStatus;
@Column({ name: 'status', type: 'varchar', default: VehicleStatus.ACTIVE, nullable: true })
status?: VehicleStatus;
@Column({ type: 'text', nullable: true })
description!: string | null;
description?: string | null;
@Column({ name: 'assigned_driver_id', type: 'uuid', nullable: true })
assignedDriverId?: string;
@Column({ name: 'assigned_driver_name', nullable: true })
assignedDriverName?: string;
}

View File

@@ -1,7 +1,7 @@
import { BaseRepository } from '@edr/api-common';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BaseRepository } from '@edr/api-common';
import { Vehicle } from './entities/vehicle.entity';
@Injectable()
@@ -12,4 +12,68 @@ export class VehiclesRepository extends BaseRepository<Vehicle> {
) {
super(repository);
}
async findByPlateNumber(plateNumber: string): Promise<Vehicle | null> {
return this.repository.findOne({ where: { plateNumber } });
}
async findVehicleById(id: string): Promise<Vehicle | null> {
return this.repository.findOne({ where: { id } });
}
async findAllWithFilters(query: {
page?: number;
pageSize?: number;
search?: string;
status?: string;
sortBy?: string;
sortOrder?: 'ASC' | 'DESC';
}) {
const page = query.page || 1;
const pageSize = query.pageSize || 10;
const skip = (page - 1) * pageSize;
let queryBuilder = this.repository.createQueryBuilder('vehicle');
if (query.search) {
queryBuilder = queryBuilder.where(
'(vehicle.plateNumber ILIKE :search OR vehicle.manufacturer ILIKE :search OR vehicle.model ILIKE :search)',
{ search: `%${query.search}%` },
);
}
if (query.status) {
queryBuilder = queryBuilder.andWhere('vehicle.status = :status', {
status: query.status,
});
}
const sortBy = query.sortBy || 'createdAt';
const sortOrder = query.sortOrder || 'DESC';
queryBuilder = queryBuilder
.orderBy(`vehicle.${sortBy}`, sortOrder)
.skip(skip)
.take(pageSize);
const [data, total] = await queryBuilder.getManyAndCount();
return {
data,
total,
page,
pageSize,
totalPages: Math.ceil(total / pageSize),
};
}
async createVehicle(vehicleData: any): Promise<Vehicle> {
const vehicle = this.repository.create(vehicleData);
const vehicles = await this.repository.save(vehicle);
return vehicles?.[0] as Vehicle;
}
async updateVehicle(vehicle: Vehicle): Promise<Vehicle> {
return (await this.repository.save(vehicle)) as Vehicle;
}
}

View File

@@ -39,14 +39,7 @@ export class VehiclesService {
limit?: number;
sortBy?: string;
sortOrder?: 'ASC' | 'DESC';
} = {}): Promise<{ data: Vehicle[]; total: number; page: number; limit: number }> {
const page = query.page || 1;
const limit = query.limit || 10;
const skip = (page - 1) * limit;
const where: any = {};
if (query.status) where.status = query.status;
} = {}): Promise<Vehicle[]> {
let qb = this.vehicleRepo.createQueryBuilder('v');
if (query.search) {
@@ -67,13 +60,9 @@ export class VehiclesService {
: 'createdAt';
const sortOrder = (query.sortOrder ?? 'DESC').toUpperCase();
const [data, total] = await qb
return qb
.orderBy(`v.${sortBy}`, sortOrder as 'ASC' | 'DESC')
.skip(skip)
.take(limit)
.getManyAndCount();
return { data, total, page, limit };
.getMany();
}
async findById(id: string): Promise<Vehicle> {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{d as N,r as c,az as S,j as t,v as u}from"./index-7T7TTikv.js";import{C as U,a as A,b as y,d as z}from"./card-_ldW-koX.js";import{S as I,a as k,b as w,c as P,d as E}from"./select--i8koVXg.js";import{A as T}from"./AdvancedTable-vWyUWUDX.js";import{u as F,A as L}from"./ArchivedUserColumnDefn-Ja27QDEy.js";import{u as V}from"./useUnit-CRt6YBLp.js";import"./table-D_B7hhqb.js";import"./chevron-left-G_a9-f9o.js";import"./utils-N2wtfq7C.js";import"./badge-D4t6Wb1T.js";import"./command-B6S1IvD4.js";import"./search-y8VSu0lZ.js";import"./popover-CSKEA8hg.js";import"./Popover-BSKEfTKH.js";import"./use-uncontrolled-tg0LIUAX.js";import"./separator-BXi_hr72.js";import"./refresh-cw-B7fipPS4.js";import"./organizationsService-DIFVjoLn.js";import"./alert-dialog-DwppaTz4.js";import"./useEmployeePostions-BZG3u-zs.js";import"./employeePositionsService-C7MSoCNC.js";import"./ellipsis-vertical-CoMd89ns.js";import"./square-pen-Dh1zj83N.js";import"./user-plus-tzUBEFtH.js";import"./unitService-DTtkt-Pb.js";const ce=()=>{var p,h,x,g,f;const{user:i}=N(),{getList:j}=V(),[o,b]=c.useState(0),s=10,v=S(),l=i!=null&&i.employee&&i.employee.length>0?i.employee[0].organizationId:void 0,{data:e}=l?j(l,{take:300,skip:0}):{data:void 0},[d,n]=c.useState(((h=(p=e==null?void 0:e.data)==null?void 0:p.items[0])==null?void 0:h.id)||"All");c.useEffect(()=>{var r;((r=e==null?void 0:e.data)==null?void 0:r.items.length)>0&&n(e==null?void 0:e.data.items[0].id)},[(x=e==null?void 0:e.data)==null?void 0:x.items]);const m=r=>{b(r)},{data:a,refetch:C}=F(d,{take:s,skip:o*s});return t.jsx("div",{className:"p-6 space-y-6",children:t.jsxs(U,{className:"col-span-2 shadow-none border-none bg-transparent px-0",children:[t.jsx(A,{className:"flex flex-row justify-between items-center px-0",children:t.jsx(y,{className:"text-xl font-semibold ",children:u("setting.archivedUsers")})}),((f=(g=e==null?void 0:e.data)==null?void 0:g.items)==null?void 0:f.length)>0&&t.jsxs("div",{className:"mb-4 w-1/2",children:[t.jsx("label",{className:"block text-sm font-medium text-gray-700",children:u("organization.selectUnit")}),t.jsxs(I,{value:d,onValueChange:r=>n(r),children:[t.jsx(k,{className:"mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm",children:t.jsx(w,{placeholder:"Select a Unit"})}),t.jsx(P,{children:e==null?void 0:e.data.items.map(r=>t.jsx(E,{value:r.id,children:v(r.name)},r.id))})]})]}),t.jsx(z,{className:"px-0",children:t.jsx(T,{columns:L,data:(a==null?void 0:a.items)||[],tableName:"ArchivedUsers",toolBarPosition:"right",itemCount:(a==null?void 0:a.count)||0,pageIndex:o,onPageChange:m,nextFunction:a!=null&&a.count&&a.count>(o+1)*s?()=>m(o+1):()=>{},prevFunction:o>0?()=>m(Math.max(o-1,0)):()=>{},refresh:C})})]})})};export{ce as default};

View File

@@ -0,0 +1,6 @@
import{y as S,u as R,d as T,az as B,r as l,j as e,B as d,A as F}from"./index-7T7TTikv.js";import{C as K,a as L,b as M,d as q}from"./card-_ldW-koX.js";import{S as E,a as V,b as _,c as H,d as G}from"./select--i8koVXg.js";import{A as j}from"./AdvancedTable-vWyUWUDX.js";import{u as J}from"./useUnit-CRt6YBLp.js";import{a as O,b as Q,u as W}from"./useArchived-5V0W60Gf.js";import{A as N}from"./archive-restore-CbEMfc7_.js";import"./table-D_B7hhqb.js";import"./chevron-left-G_a9-f9o.js";import"./utils-N2wtfq7C.js";import"./badge-D4t6Wb1T.js";import"./command-B6S1IvD4.js";import"./search-y8VSu0lZ.js";import"./popover-CSKEA8hg.js";import"./Popover-BSKEfTKH.js";import"./use-uncontrolled-tg0LIUAX.js";import"./separator-BXi_hr72.js";import"./refresh-cw-B7fipPS4.js";import"./unitService-DTtkt-Pb.js";import"./positionService-BwPU5sNe.js";import"./organizationsService-DIFVjoLn.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const X=[["path",{d:"M18 21a6 6 0 0 0-12 0",key:"kaz2du"}],["circle",{cx:"12",cy:"11",r:"4",key:"1gt34v"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Y=S("square-user-round",X),fe=()=>{var y;const{t}=R(),{user:i}=T(),m=B(),{getList:A}=J(),h=i!=null&&i.employee&&i.employee.length>0?i.employee[0].organizationId:void 0,[r,x]=l.useState("units"),[u,g]=l.useState(""),{data:p}=h?A(h,{take:300,skip:0}):{data:void 0},c=((y=p==null?void 0:p.data)==null?void 0:y.items)??[];!u&&c.length>0&&g(c[0].id);const{data:a,refetch:b}=O(h),{data:n,refetch:k}=Q(u||void 0),{restoreUnit:C,isRestoringUnit:U,restorePosition:z,isRestoringPosition:P}=W(),v=l.useMemo(()=>(a==null?void 0:a.items)??a??[],[a]),f=l.useMemo(()=>(n==null?void 0:n.items)??n??[],[n]),I=[{id:"name",header:t("organization.name","Name"),cell:({row:s})=>{var o;return m((o=s.original)==null?void 0:o.name)||"—"}},{id:"key",header:t("organization.key","Key"),accessorKey:"key"},{id:"actions",header:t("userIncomingretun.Actions","Actions"),cell:({row:s})=>e.jsxs(d,{size:"sm",variant:"outline",disabled:U,onClick:()=>C(s.original.id),className:"flex items-center gap-2 text-primary-700 hover:bg-primary-50",children:[e.jsx(N,{className:"h-4 w-4"}),t("archive.restore","Restore")]})}],w=[{id:"name",header:t("organization.name","Name"),cell:({row:s})=>{var o;return m((o=s.original)==null?void 0:o.name)||"—"}},{id:"key",header:t("organization.key","Key"),accessorKey:"key"},{id:"actions",header:t("userIncomingretun.Actions","Actions"),cell:({row:s})=>e.jsxs(d,{size:"sm",variant:"outline",disabled:P,onClick:()=>z(s.original.id),className:"flex items-center gap-2 text-primary-700 hover:bg-primary-50",children:[e.jsx(N,{className:"h-4 w-4"}),t("archive.restore","Restore")]})}];return e.jsx("div",{className:"p-6 space-y-6",children:e.jsxs(K,{className:"shadow-none border-none bg-transparent px-0",children:[e.jsx(L,{className:"flex flex-row justify-between items-center px-0",children:e.jsx(M,{className:"text-xl font-semibold",children:t("archive.archivedItems","Archived Items")})}),e.jsxs("div",{className:"flex gap-2 mb-4",children:[e.jsxs(d,{variant:r==="units"?"default":"outline",onClick:()=>x("units"),className:"flex items-center gap-2",children:[e.jsx(F,{className:"h-4 w-4"}),t("archive.archivedUnits","Archived Units")]}),e.jsxs(d,{variant:r==="positions"?"default":"outline",onClick:()=>x("positions"),className:"flex items-center gap-2",children:[e.jsx(Y,{className:"h-4 w-4"}),t("archive.archivedPositions","Archived Positions")]})]}),r==="positions"&&c.length>0&&e.jsxs("div",{className:"mb-4 w-full sm:w-1/2",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-200",children:t("organization.selectUnit","Select Unit")}),e.jsxs(E,{value:u,onValueChange:s=>g(s),children:[e.jsx(V,{className:"mt-1 block w-full",children:e.jsx(_,{placeholder:t("organization.selectUnit")})}),e.jsx(H,{children:c.map(s=>e.jsx(G,{value:s.id,children:m(s.name)},s.id))})]})]}),e.jsx(q,{className:"px-0",children:r==="units"?e.jsx(j,{columns:I,data:v,tableName:"ArchivedUnits",toolBarPosition:"right",itemCount:v.length,pageIndex:0,onPageChange:()=>{},nextFunction:()=>{},prevFunction:()=>{},refresh:b}):e.jsx(j,{columns:w,data:f,tableName:"ArchivedPositions",toolBarPosition:"right",itemCount:f.length,pageIndex:0,onPageChange:()=>{},nextFunction:()=>{},prevFunction:()=>{},refresh:k})})]})})};export{fe as default};

View File

@@ -0,0 +1 @@
import{d as v}from"./organizationsService-DIFVjoLn.js";import{n as j,r as d,u as A,k as f,j as e,B as g,aF as w,f as D,aA as y,aB as b,aC as C,aD as N,v as o,aE as x,b_ as S,az as E}from"./index-7T7TTikv.js";import{A as O,a as M,b as R,c as U,d as T,e as B,f as L}from"./alert-dialog-DwppaTz4.js";import{u as z,T as F}from"./useEmployeePostions-BZG3u-zs.js";import{E as I}from"./ellipsis-vertical-CoMd89ns.js";import{S as k}from"./square-pen-Dh1zj83N.js";import{U as q}from"./user-plus-tzUBEFtH.js";import{B as K}from"./badge-D4t6Wb1T.js";const Z=(s,r)=>j({queryKey:["archived-users",s,r],queryFn:async()=>{if(!s)return{items:[],count:0};const{data:a}=await v(s,r);return a},enabled:!!s}),P=({isOpen:s,onClose:r,userId:a})=>{const{activateUser:t,isActivatingUser:i}=z(),[n,c]=d.useState(!1),{t:l}=A(),{handleError:u}=f(l),h=async()=>{try{await t({payload:a,successCallback:()=>{r()}}),c(!0)}catch(m){u(m)}};return e.jsx(O,{open:s,onOpenChange:r,children:e.jsxs(M,{children:[e.jsxs(R,{children:[e.jsx(U,{children:"Remove team member from this position?"}),e.jsx(T,{children:"Are you sure you want to activate this archived user? This action will restore the user's access and data within the organization."})]}),e.jsxs(B,{children:[e.jsx(L,{disabled:n,children:"Cancel"}),e.jsxs(g,{variant:"destructive",onClick:h,disabled:n,children:[i&&e.jsx(w,{className:"h-4 w-4 mr-2 animate-spin"}),"Confirm"]})]})]})})},H=({row:s})=>{const r=D(),[a,t]=d.useState(!1),[i,n]=d.useState(!1),[c,l]=d.useState(!1),u=()=>{r(`/user-management/archive/edit/${s==null?void 0:s.userId}`)},h=p=>{p.preventDefault(),t(!1),n(!0)},m=()=>{l(!0)};return e.jsxs(e.Fragment,{children:[e.jsxs(y,{open:a,onOpenChange:t,children:[e.jsx(b,{asChild:!0,children:e.jsxs(g,{variant:"ghost",className:"h-8 w-8 p-0",children:[e.jsx(I,{className:"h-4 w-4"}),e.jsx("span",{className:"sr-only",children:"Open actions menu"})]})}),e.jsxs(C,{align:"end",onInteractOutside:p=>{p.target.closest('[role="dialog"]')||t(!1)},children:[e.jsx(N,{children:o("userRecord.Actions")}),e.jsxs(x,{onSelect:u,className:"cursor-pointer hover:!text-primary-700 !bg-transparent !transition-colors duration-200",children:[e.jsx(k,{className:"mr-2 h-4 w-4 group-hover:text-white transition-colors duration-200"}),e.jsxs("span",{children:[" ",o("userRecord.Edit")]})]}),e.jsxs(x,{onSelect:m,className:"cursor-pointer hover:!text-primary-700 !bg-transparent !transition-colors duration-200",children:[e.jsx(q,{className:"mr-2 h-4 w-4 group-hover:text-white transition-colors duration-200"}),e.jsxs("span",{children:[" ",o("userRecord.Activate")]})]}),e.jsx(S,{}),e.jsxs(x,{onSelect:h,className:"text-red-600 cursor-pointer hover:!text-red-800 !bg-transparent !transition-colors duration-200",children:[e.jsx(F,{className:"mr-2 h-4 w-4 text-red-600 group-hover:text-white transition-colors duration-200"}),e.jsxs("span",{children:[" ",o("userRecord.Delete")]})]})]})]}),c&&e.jsx(P,{isOpen:c,onClose:()=>l(!1),userId:s.id})]})},ee=[{accessorKey:"name",header:()=>o("setting.Name"),cell:({row:s})=>{var t;const r=E(),a=(t=s.original)==null?void 0:t.name;return e.jsx("span",{children:r(a)})}},{accessorKey:"status",header:()=>o("userRecord.Status"),cell:({row:s})=>{var i;const r=(i=s.original)==null?void 0:i.status,a=n=>{switch(n.toLowerCase()){case"inactive":return"bg-red-100 text-red-600 hover:bg-red-100";case"active":return"bg-primary-100 text-primary-600 hover:bg-primary-100";default:return"bg-gray-100 text-gray-600 hover:bg-gray-100"}},t=n=>{switch(n.toLowerCase()){case"inactive":return"InActive";case"active":return"Active";default:return"Not Available"}};return e.jsx("div",{children:e.jsx(K,{className:`${a(r)} rounded-full px-6 py-1 font-medium`,children:t(r)})})}},{id:"actions",header:()=>o("userRecord.Actions"),cell:({row:s})=>e.jsx(H,{row:s.original})}];export{ee as A,Z as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{r as n,j as r,bj as c}from"./index-7T7TTikv.js";import{u as z}from"./useOrganizations-CPt4mkXS.js";import{O}from"./OrganizationForm-BNuDw3k3.js";import"./organizationsService-DIFVjoLn.js";import"./select--i8koVXg.js";import"./card-_ldW-koX.js";import"./label-CABYEcfW.js";import"./useOrganizationTypes-CQm1BLlI.js";import"./index.esm-BRNlF2G3.js";import"./zod-D-9d3Txu.js";import"./switch-D9hx8CZw.js";import"./Switch-ByfhjkDo.js";import"./InputsGroupFieldset-B16dMH0P.js";import"./use-uncontrolled-tg0LIUAX.js";const f=({id:i})=>{const[a,e]=n.useState(),{editOrganization:s,isEditing:m,getOrganizationByDetails:p}=z("Org"),g=()=>{p(i,{onSuccess:t=>{e(t)}})};n.useEffect(()=>{g()},[]);const d=t=>{const o={key:t.key,name:t.name,organizationTypeId:t.organizationTypeId,isGovernmentOrganization:t.isGovernmentOrganization};t.parentId&&t.parentId!==""&&(o.parentId=t.parentId),s({id:i,payload:o})};return r.jsx(O,{isLoading:m,onSubmit:t=>d(t),type:"Edit",organizationDetails:a})},h=()=>{const{id:i}=c();return i&&r.jsx(f,{id:i})};export{h as default};

View File

@@ -0,0 +1 @@
import{u as b,f as w,r as l,j as e,H as j,I as N,B as h,h as y,t as p}from"./index-7T7TTikv.js";import{b as v}from"./Utils-BP0IYDrC.js";import{L as k}from"./lock-DGEqses-.js";import{P as C}from"./phone-w_VmAt3l.js";import{M as f}from"./mail-q8lHlEPt.js";import{R as P}from"./refresh-cw-B7fipPS4.js";import{A as S}from"./arrow-left-mae9HpSL.js";const F=()=>{const{t:s}=b(),t=w(),[n,u]=l.useState(""),[d,c]=l.useState(!1),[m,a]=l.useState(""),g=async o=>{o.preventDefault(),a("");let r=n;if(!v(r)){a(s("forgotpassword.invalidphone"));return}r.startsWith("0")&&(r="+251"+r.slice(1)),c(!0);try{await y(r),p.success(s("forgotpassword.success"),{description:s("forgotpassword.successdesc")}),setTimeout(()=>t("/"),3e3)}catch(i){const x=(i==null?void 0:i.message)||s("forgotpassword.fail");a(x),p.error(s("forgotpassword.fail"),{description:x})}finally{c(!1)}};return e.jsxs("div",{className:"min-h-screen bg-gradient-to-br from-cyan-50 via-white to-primary-50 relative overflow-hidden",children:[e.jsx("div",{className:"absolute top-0 right-0 w-96 h-96 bg-cyan-100/30 rounded-full blur-3xl"}),e.jsx("div",{className:"absolute bottom-0 left-0 w-96 h-96 bg-primary-100/30 rounded-full blur-3xl"}),e.jsxs("button",{onClick:()=>t("/"),className:"absolute top-6 left-6 z-10 flex items-center gap-2 px-4 py-2 bg-white/80 backdrop-blur-sm hover:bg-white rounded-full shadow-md hover:shadow-lg transition-all duration-300 group",children:[e.jsx(j,{className:"w-4 h-4 text-primary group-hover:scale-110 transition-transform"}),e.jsx("span",{className:"text-sm font-medium text-gray-700",children:s("forgotpassword.home")})]}),e.jsx("div",{className:"relative min-h-screen flex items-center justify-center p-4",children:e.jsxs("div",{className:"w-full max-w-md",children:[e.jsxs("div",{className:"bg-white rounded-2xl shadow-xl border border-gray-100 overflow-hidden",children:[e.jsxs("div",{className:"bg-gradient-to-r from-primary to-primary-500 p-8 text-center relative",children:[e.jsx("div",{className:"absolute inset-0 bg-white/5"}),e.jsxs("div",{className:"relative",children:[e.jsx("div",{className:"w-16 h-16 bg-white/20 backdrop-blur-sm rounded-full flex items-center justify-center mx-auto mb-4",children:e.jsx(k,{className:"w-8 h-8 text-white"})}),e.jsx("h1",{className:"text-2xl font-bold text-white mb-2",children:s("forgotpassword.title")}),e.jsx("p",{className:"text-cyan-50 text-sm",children:s("forgotpassword.subtitle")})]})]}),e.jsx("div",{className:"p-8",children:e.jsxs("form",{onSubmit:g,className:"space-y-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("label",{className:"text-sm font-medium text-gray-700 flex items-center gap-2",children:[e.jsx(C,{className:"w-4 h-4 text-primary"}),s("forgotpassword.phone")]}),e.jsx("div",{className:"relative",children:e.jsx(N,{type:"tel",placeholder:s("forgotpassword.phoneplaceholder"),className:"h-12 rounded-lg border-gray-200 px-4 text-sm focus:border-primary focus:ring-primary transition-all",value:n,onChange:o=>{u(o.target.value),a("")},required:!0})}),m&&e.jsxs("div",{className:"flex items-start gap-2 p-3 bg-red-50 border border-red-100 rounded-lg",children:[e.jsx("div",{className:"w-1 h-1 bg-red-500 rounded-full mt-1.5"}),e.jsx("p",{className:"text-sm text-red-600 flex-1",children:m})]})]}),e.jsxs("div",{className:"flex items-start gap-3 p-4 bg-cyan-50 border border-cyan-100 rounded-lg",children:[e.jsx(f,{className:"w-5 h-5 text-primary flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm text-gray-700 font-medium mb-1",children:s("forgotpassword.checkphone")}),e.jsx("p",{className:"text-xs text-gray-600",children:s("forgotpassword.checkdesc")})]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(h,{type:"submit",className:"w-full h-12 bg-primary hover:bg-primary-500 text-white text-sm font-medium rounded-lg shadow-md hover:shadow-lg transition-all duration-300",disabled:d,children:d?e.jsxs("span",{className:"flex items-center justify-center gap-2",children:[e.jsx(P,{className:"animate-spin h-5 w-5"}),s("forgotpassword.sending")]}):e.jsxs("span",{className:"flex items-center justify-center gap-2",children:[e.jsx(f,{className:"h-5 w-5"}),s("forgotpassword.sendresetlink")]})}),e.jsxs(h,{type:"button",variant:"outline",className:"w-full h-12 text-sm font-medium border-gray-200 hover:bg-gray-50 rounded-lg transition-all duration-300 bg-transparent",onClick:()=>t("/login"),children:[e.jsx(S,{className:"h-4 w-4 mr-2"}),s("forgotpassword.backtologin")]})]})]})})]}),e.jsxs("p",{className:"text-center text-sm text-gray-500 mt-6",children:[s("forgotpassword.remember")," ",e.jsx("button",{onClick:()=>t("/login"),className:"text-primary hover:text-primary-500 font-medium transition-colors",children:s("forgotpassword.signin")})]})]})})]})};export{F as ForgotPassword,F as default};

View File

@@ -0,0 +1 @@
import{r as i,j as n,B as k,aI as u}from"./index-7T7TTikv.js";import"./form-lLGtsTgY.js";import"./multi-select-CZLBnGmP.js";import"./single-select-CqAjmX3L.js";i.createContext({open:!1,setOpen:()=>{}});const O=({label:h,options:x,value:o,onChange:j,collapsible:f=!1,localizedName:r})=>{const[l,b]=i.useState(!f),[m,S]=i.useState(new Set),w=t=>{const e=new Set(m);e.has(t)?e.delete(t):e.add(t),S(e)},g=t=>{j(t)},p=(t,e=[])=>{for(const s of t){const a=typeof s.name=="string"?s.name:(r==null?void 0:r(s.name))??s.name.en;if(s.id===o)return[...e,a].join(" / ");if(s.children&&s.children.length>0){const c=p(s.children,[...e,a]);if(c)return c}}return null},d=t=>t.flatMap(e=>{const s=e.children&&e.children.length>0,a=m.has(e.id),c=s?e.children.some(v=>v.id===o):!1;if(s&&e.children.length===1)return d(e.children);const C=typeof e.name=="string"?e.name:(r==null?void 0:r(e.name))??e.name.en;return n.jsxs("div",{className:"ml-4 mb-1",children:[n.jsxs("div",{className:"flex items-center space-x-2",children:[s&&n.jsx("button",{type:"button",onClick:()=>w(e.id),className:"w-4 h-4 flex items-center justify-center",children:n.jsx(u,{className:`h-3 w-3 transition-transform ${a?"rotate-180":""}`})}),n.jsxs("label",{className:"flex items-center space-x-2",children:[n.jsx("input",{type:"radio",name:"unit-select",checked:o===e.id||c,onChange:()=>g(e.id)}),n.jsx("span",{className:c?"font-semibold":"",children:C})]})]}),s&&a&&n.jsx("div",{className:"ml-4",children:d(e.children)})]},e.id)}),y=p(x);return n.jsxs("div",{className:"mb-4",children:[n.jsx("label",{className:"block font-semibold mb-1",children:h}),f&&n.jsxs(k,{type:"button",variant:"outline",onClick:()=>b(!l),className:"w-full justify-between mb-2",children:[n.jsx("span",{children:y??`Select ${h.toLowerCase()}`}),n.jsx(u,{className:`h-4 w-4 transition-transform ${l?"rotate-180":""}`})]}),l&&n.jsx("div",{className:"border rounded-md p-2 bg-background max-h-96 overflow-y-auto",children:d(x)})]})};export{O as S};

View File

@@ -0,0 +1 @@
import{r as W,V as B,j as e,Q as o,ae as x,_ as C,Z as R,at as w}from"./index-7T7TTikv.js";var u={root:"m_5f75b09e",body:"m_5f6e695e",labelWrapper:"m_d3ea56bb",label:"m_8ee546b8",description:"m_328f68c0",error:"m_8e8a99cc"};const N=u,D=W.forwardRef(({__staticSelector:t,__stylesApiProps:l,className:s,classNames:f,styles:_,unstyled:h,children:I,label:i,description:d,id:p,disabled:b,error:n,size:r,labelPosition:j="left",bodyElement:c="div",labelElement:m="label",variant:v,style:y,vars:E,mod:S,...F},g)=>{const a=B({name:t,props:l,className:s,style:y,classes:u,classNames:f,styles:_,unstyled:h});return e.jsx(o,{...a("root"),ref:g,__vars:{"--label-fz":R(r),"--label-lh":C(r,"label-lh")},mod:[{"label-position":j},S],variant:v,size:r,...F,children:e.jsxs(o,{component:c,htmlFor:c==="label"?p:void 0,...a("body"),children:[I,e.jsxs("div",{...a("labelWrapper"),"data-disabled":b||void 0,children:[i&&e.jsx(o,{component:m,htmlFor:m==="label"?p:void 0,...a("label"),"data-disabled":b||void 0,children:i}),d&&e.jsx(x.Description,{size:r,__inheritStyles:!1,...a("description"),children:d}),n&&typeof n!="boolean"&&e.jsx(x.Error,{size:r,__inheritStyles:!1,...a("error"),children:n})]})]})})});D.displayName="@mantine/core/InlineInput";function Q({children:t,role:l}){const s=w();return s?e.jsx("div",{role:l,"aria-labelledby":s.labelId,"aria-describedby":s.describedBy,children:t}):e.jsx(e.Fragment,{children:t})}export{Q as I,D as a,N as b};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{n as x,j as r,aA as b,aB as C,B as y,aC as E,aE as M,r as d,az as w,u as S,f as v}from"./index-7T7TTikv.js";import{A as z}from"./AdvancedTable-vWyUWUDX.js";import{C as I,a as K,b as B,d as T}from"./card-_ldW-koX.js";import{a as A}from"./userService-CFvyXTYe.js";import{E as U}from"./ellipsis-DBW5EePE.js";import{E as L}from"./eye-DYwZYJcQ.js";import{f as P}from"./organizationService-B_C-b9EH.js";import{S as k}from"./FormFields-DeF71qnl.js";import"./table-D_B7hhqb.js";import"./select--i8koVXg.js";import"./chevron-left-G_a9-f9o.js";import"./utils-N2wtfq7C.js";import"./badge-D4t6Wb1T.js";import"./command-B6S1IvD4.js";import"./search-y8VSu0lZ.js";import"./popover-CSKEA8hg.js";import"./Popover-BSKEfTKH.js";import"./use-uncontrolled-tg0LIUAX.js";import"./separator-BXi_hr72.js";import"./refresh-cw-B7fipPS4.js";import"./form-lLGtsTgY.js";import"./index.esm-BRNlF2G3.js";import"./label-CABYEcfW.js";import"./multi-select-CZLBnGmP.js";import"./single-select-CqAjmX3L.js";const q=(n,l)=>x({queryKey:["migratedData",n,l],queryFn:async()=>{const{data:m}=await A(n,l);return m}}),F=(n,l,m)=>{const g=t=>{m(`/user-management/migrated-records-management/view/${t}`)};return[{accessorKey:"record.referenceNumber",header:"Reference Number",cell:({row:t})=>{var e,a;return(a=(e=t.original)==null?void 0:e.record)==null?void 0:a.referenceNumber}},{accessorKey:"record.letterNumber",header:"Letter Number",cell:({row:t})=>{var e,a;return(a=(e=t.original)==null?void 0:e.record)==null?void 0:a.letterNumber}},{accessorKey:"record.metadata.uploadedBy.en",header:"Uploaded By",cell:({row:t})=>{var e,a,s;return n(((s=(a=(e=t.original)==null?void 0:e.record)==null?void 0:a.metadata)==null?void 0:s.uploadedBy)??{en:"-",am:"-"})}},{accessorKey:"record.metadata.organizationName.en",header:"Organization",cell:({row:t})=>{var e,a,s;return n(((s=(a=(e=t.original)==null?void 0:e.record)==null?void 0:a.metadata)==null?void 0:s.organizationName)??{en:"-",am:"-"})}},{accessorKey:"record.dispatchedDate",header:"Dispatched Date",cell:({row:t})=>{var e,a;return new Date((a=(e=t.original)==null?void 0:e.record)==null?void 0:a.dispatchedDate).toLocaleString()}},{accessorKey:"status",header:"Status",cell:({row:t})=>{var e;return(e=t.original)==null?void 0:e.status}},{accessorKey:"record.content",header:"Subject",cell:({row:t})=>{var e,a,s;return((s=(a=(e=t.original)==null?void 0:e.record)==null?void 0:a.content[0])==null?void 0:s.subject)||"-"}},{id:"actions",cell:({row:t})=>{const e=t.original.record;return r.jsxs(b,{children:[r.jsx(C,{asChild:!0,children:r.jsx(y,{variant:"ghost",size:"sm",children:r.jsx(U,{className:"h-4 w-4"})})}),r.jsx(E,{align:"end",children:r.jsxs(M,{onClick:()=>g(e.id),children:[r.jsx(L,{className:"h-4 w-4 mr-2"}),l("userRecord.View")]})})]})}}]};function V(){const[n,l]=d.useState(0),m=10,[g,t]=d.useState(!1),e=w(),{t:a}=S(),s=v(),{data:o,isLoading:O,error:H}=x({queryKey:["organizations"],queryFn:P,staleTime:300*1e3}),[u,h]=d.useState(null),j=d.useMemo(()=>(o==null?void 0:o.items.map(i=>({id:i.id,name:i.name,hierarchyType:"organization",value:i.units.length===1?i.units[0].id:"",children:Array.isArray(i.units)&&i.units.length>0?i.units.map(c=>({id:c.id,name:c.name,hierarchyType:"unit",value:c.id,children:[]})):[]})))||[],[o,e]);d.useEffect(()=>{if(!u){const i=o==null?void 0:o.items.flatMap(c=>c.units).find(c=>c.id);i&&h(i.id)}},[o]),d.useEffect(()=>{u&&sessionStorage.setItem("selectedUnitId",u)},[u]),d.useEffect(()=>{const i=sessionStorage.getItem("selectedUnitId");i&&h(i)},[]);const{data:p,isLoading:D}=q(u??"",{skip:n*m,take:m,orderBy:"migratedAt:DESC"}),f=i=>{l(i)},N=()=>{t(!0)};return D?r.jsx("div",{children:a("loading")}):r.jsx("div",{className:"p-6 space-y-6",children:r.jsxs(I,{className:"col-span-2 shadow-none border-none bg-transparent px-0",children:[r.jsxs(K,{className:"flex flex-row justify-between items-center px-0",children:[r.jsx(B,{className:"text-xl font-semibold ",children:a("migration.migratedData")}),r.jsx(y,{onClick:N,children:a(g?"migration.exporting":"migration.exportData")})]}),r.jsx("div",{className:"mb-4",children:r.jsx(k,{label:a("selectUnit"),options:j,value:u,onChange:h,collapsible:!0})}),r.jsx(T,{className:"px-0",children:r.jsx(z,{columns:F(e,a,s),data:(p==null?void 0:p.items)||[],tableName:"Migrated Data",toolBarPosition:"right",itemCount:(p==null?void 0:p.count)||0,pageIndex:n,onPageChange:f,nextFunction:()=>f(n+1),prevFunction:()=>f(Math.max(n-1,0))})})]})})}function he(){return r.jsx(V,{})}export{he as default};

View File

@@ -0,0 +1 @@
import{j as i}from"./index-7T7TTikv.js";import{u as m}from"./useOrganizations-CPt4mkXS.js";import{O as e}from"./OrganizationForm-BNuDw3k3.js";import"./organizationsService-DIFVjoLn.js";import"./select--i8koVXg.js";import"./card-_ldW-koX.js";import"./label-CABYEcfW.js";import"./useOrganizationTypes-CQm1BLlI.js";import"./index.esm-BRNlF2G3.js";import"./zod-D-9d3Txu.js";import"./switch-D9hx8CZw.js";import"./Switch-ByfhjkDo.js";import"./InputsGroupFieldset-B16dMH0P.js";import"./use-uncontrolled-tg0LIUAX.js";const p=()=>{const{createOrganization:o,isCreating:n}=m("Org"),a=t=>{const r={key:t.key,name:t.name,organizationTypeId:t.organizationTypeId,isGovernmentOrganization:t.isGovernmentOrganization};t.parentId&&t.parentId!==""&&(r.parentId=t.parentId),o(r)};return i.jsx(e,{isLoading:n,onSubmit:t=>a(t),type:"Create"})},w=()=>i.jsx(p,{});export{w as default};

View File

@@ -0,0 +1,6 @@
import{y as C,f as A,d as S,z as M,F as x,v as a,j as e,B as u,A as D}from"./index-7T7TTikv.js";import{C as n,d as l,a as U,b as z}from"./card-_ldW-koX.js";import{u as $}from"./useOrganizationReport-Btcu9b-4.js";import{A as L,a as E}from"./alert-CCWXLU2U.js";import{S as c}from"./skeleton-BCpLdfqO.js";import{S as R}from"./SmartOfficeAuditPage-Dcwrs1dM.js";import{U as b}from"./users-bn5-xqQf.js";import{C as f}from"./circle-alert-HVqsZpe-.js";import{R as j}from"./refresh-cw-B7fipPS4.js";import"./organizationsService-DIFVjoLn.js";import"./Skeleton-BOu0YqbY.js";import"./table-D_B7hhqb.js";import"./badge-D4t6Wb1T.js";import"./avatar-BU_IHgzI.js";import"./format-DvwV82px.js";import"./en-US-Cc-9gH5A.js";import"./shield-D3luOm6l.js";import"./lock-DGEqses-.js";import"./eye-DYwZYJcQ.js";import"./square-pen-Dh1zj83N.js";import"./download-Btm1n-GQ.js";import"./select--i8koVXg.js";import"./popover-CSKEA8hg.js";import"./Popover-BSKEfTKH.js";import"./use-uncontrolled-tg0LIUAX.js";import"./endOfMonth-DmxQbzXi.js";import"./search-y8VSu0lZ.js";import"./label-CABYEcfW.js";import"./radio-group-C9tEhs3a.js";import"./Radio-D43EoWlg.js";import"./get-auto-contrast-value-Da6zqqWm.js";import"./InputsGroupFieldset-B16dMH0P.js";import"./checkbox-CTVlz2xL.js";import"./Checkbox-CAXGYFGh.js";import"./eye-off-AoIvdwmO.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const _=[["path",{d:"M20 7h-3a2 2 0 0 1-2-2V2",key:"x099mo"}],["path",{d:"M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z",key:"18t6ie"}],["path",{d:"M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8",key:"1nja0z"}]],B=C("files",_),je=()=>{var g,h;const t=A(),{user:i}=S(),y=((h=(g=i==null?void 0:i.employee)==null?void 0:g[0])==null?void 0:h.organizationId)||"fecaa9b3-0b9d-4772-a7c7-bcb19d46122a",{report:s,isLoading:d,isError:v,error:m,refetch:N}=$(y),k=()=>{var r,o,p;return[{id:"employees",title:a("dashboard.totalEmployees"),value:((r=s==null?void 0:s.employeesCount)==null?void 0:r.toLocaleString())||"0",icon:b,color:"from-blue-500 to-blue-600"},{id:"units",title:a("dashboard.totalUnits"),value:((o=s==null?void 0:s.unitsCount)==null?void 0:o.toLocaleString())||"0",icon:D,color:"from-primary-500 to-primary-600"},{id:"positions",title:a("dashboard.totalPositions"),value:((p=s==null?void 0:s.positionsCount)==null?void 0:p.toLocaleString())||"0",icon:x,color:"from-purple-500 to-purple-600"}]},w=[{id:"user-mgmt",title:a("dashboard.userManagement"),description:a("dashboard.userManagementDesc"),icon:b,action:()=>t("/user-management/user_management"),color:"bg-gradient-to-r from-blue-500 to-cyan-600"},{id:"content-mgmt",title:a("dashboard.contentManagement"),description:a("dashboard.contentManagementDesc"),icon:B,action:()=>t("/user-management/content-management"),color:"bg-gradient-to-r from-purple-500 to-indigo-600"},{id:"excel-upload",title:a("dashboard.excelUploader"),description:a("dashboard.excelUploaderDesc"),icon:M,action:()=>t("/user-management/bulk-upload"),color:"bg-gradient-to-r from-primary-500 to-primary-600"},{id:"position-settings",title:a("dashboard.positionSettings"),description:a("dashboard.positionSettingsDesc"),icon:x,action:()=>t("/user-management/position-management"),color:"bg-gradient-to-r from-orange-500 to-red-600"},{id:"archive-users",title:a("dashboard.archiveUsers"),description:a("dashboard.archiveUsersDesc"),icon:f,action:()=>t("/user-management/archives"),color:"bg-gradient-to-r from-gray-500 to-slate-600"}];return e.jsxs("div",{className:"mx-auto p-6 space-y-6",children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-bold text-gray-900 dark:text-gray-100",children:a("dashboard.organizationDashboard")}),e.jsx("p",{className:"text-muted-foreground dark:text-gray-400",children:a("dashboard.orgMsg")})]}),e.jsxs(u,{variant:"outline",size:"sm",onClick:()=>N(),disabled:d,children:[e.jsx(j,{className:`h-4 w-4 mr-2 ${d?"animate-spin":""}`}),a("dashboard.refresh")]})]}),v&&e.jsxs(L,{variant:"destructive",children:[e.jsx(f,{className:"h-4 w-4"}),e.jsxs(E,{children:[a("dashboard.errorMsg"),m instanceof Error&&`: ${m.message}`]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8",children:d?Array(3).fill(0).map((r,o)=>e.jsx(n,{className:"hover:shadow-lg transition-shadow duration-200 dark:bg-gray-800 dark:border-gray-700",children:e.jsx(l,{className:"p-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"w-full",children:[e.jsx(c,{className:"h-4 w-24 mb-2"}),e.jsx(c,{className:"h-8 w-16"})]}),e.jsx(c,{className:"h-12 w-12 rounded-full"})]})})},`skeleton-stat-${o}`)):k().map(r=>e.jsx(n,{className:"hover:shadow-lg transition-shadow duration-200 border-l-4 border-l-blue-500 dark:bg-gray-800 dark:border-gray-700 dark:border-l-blue-500",children:e.jsx(l,{className:"p-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-muted-foreground dark:text-gray-400",children:r.title}),e.jsx("h3",{className:"text-3xl font-bold mt-2 text-gray-900 dark:text-gray-100",children:r.value})]}),e.jsx("div",{className:`p-4 rounded-full bg-gradient-to-r ${r.color} shadow-lg`,children:e.jsx(r.icon,{className:"h-6 w-6 text-white"})})]})})},`stat-${r.id}`))}),e.jsxs(n,{className:"dark:bg-gray-800 dark:border-gray-700",children:[e.jsx(U,{children:e.jsxs(z,{className:"flex items-center dark:text-gray-100",children:[e.jsx(j,{className:"h-5 w-5 mr-2"}),a("landingPage.quickActions")]})}),e.jsx(l,{children:e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",children:w.map(r=>e.jsx(u,{onClick:r.action,className:`h-auto p-6 ${r.color} text-white hover:opacity-90 hover:scale-105 transition-all duration-200`,children:e.jsxs("div",{className:"flex flex-col items-center space-y-3 text-center",children:[e.jsx(r.icon,{className:"h-8 w-8"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold text-base",children:r.title}),e.jsx("div",{className:"text-sm opacity-90 mt-1",children:r.description})]})]})},`action-${r.id}`))})})]}),e.jsx(R,{})]})};export{je as default};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
import{y as h,az as f,j as a,A as k,H as j,bj as N}from"./index-7T7TTikv.js";import{B as g}from"./badge-D4t6Wb1T.js";import{C as v,a as w,b as z,d as C}from"./card-_ldW-koX.js";import{S as p}from"./separator-BXi_hr72.js";import{a as O}from"./useOrganizations-CPt4mkXS.js";import{u as D}from"./useOrganizationTypes-CQm1BLlI.js";import{B as y}from"./building-BTGMe3qn.js";import{S as A}from"./shield-check-CfyQTFAv.js";import"./organizationsService-DIFVjoLn.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const S=[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0",key:"1r0f0z"}],["circle",{cx:"12",cy:"10",r:"3",key:"ilqhr7"}]],B=h("map-pin",S),L=({id:d})=>{var x;const l=f(),{organizationsDetailResponse:o,isDetailLoading:u,isDetailError:b}=O("Org",d),{organizationTypesResponse:n}=D();if(u)return a.jsx("div",{children:"Loading..."});if(b||!o)return a.jsx("div",{children:"Error loading organization."});const r=o.items,c=r.organizationTypeId,m=e=>new Date(e).toLocaleString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"2-digit",minute:"2-digit"});return a.jsxs(v,{className:"w-full max-w-3xl mx-auto shadow-xl rounded-2xl border border-gray-200 bg-white dark:bg-zinc-900 transition hover:shadow-2xl",children:[a.jsxs(w,{className:"flex items-center gap-3 pb-2 border-b border-gray-200 dark:border-gray-700",children:[a.jsx(k,{className:"w-7 h-7 text-primary"}),a.jsx(z,{className:"text-2xl font-bold",children:l(r.name)})]}),a.jsxs(C,{className:"space-y-4",children:[a.jsxs("div",{className:"flex flex-wrap gap-2",children:[a.jsx(g,{variant:r.isGovernmentOrganization?"default":"outline",className:`px-3 py-1 rounded-xl ${r.isGovernmentOrganization?"bg-primary-100 text-primary-800 dark:bg-primary-800 dark:text-primary-100":"bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-100"}`,children:r.isGovernmentOrganization?"Government":"Private"}),a.jsx(g,{variant:"default",className:`px-3 py-1 rounded-xl ${r.status==="Active"?"bg-primary-100 text-primary-800 dark:bg-primary-800 dark:text-primary-100":"bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-100"}`,children:r.status})]}),a.jsx(p,{className:"my-2"}),a.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm text-gray-700 dark:text-gray-300",children:[a.jsxs("div",{className:"order-1",children:[a.jsx("p",{className:"font-semibold",children:"Created At:"}),a.jsx("p",{children:m(r.createdAt)})]}),a.jsxs("div",{className:"order-2",children:[a.jsx("p",{className:"font-semibold",children:"Updated At:"}),a.jsx("p",{children:m(r.updatedAt)})]}),a.jsxs("div",{className:"sm:col-span-2 order-3",children:[a.jsx("p",{className:"font-semibold",children:"Key:"}),a.jsx("p",{className:"break-words",children:r.key})]})]}),a.jsx(p,{className:"my-2"}),a.jsx("div",{className:"flex flex-wrap gap-2 items-center",children:c&&((x=n==null?void 0:n.items)==null?void 0:x.filter(e=>e.id===c).map(e=>{let t,s,i;switch(e.key){case"super_admin":t=A,s="bg-purple-100 dark:bg-purple-800",i="text-purple-800 dark:text-purple-100";break;case"woreda":t=B,s="bg-blue-100 dark:bg-blue-800",i="text-blue-800 dark:text-blue-100";break;case"subcity":t=j,s="bg-primary-100 dark:bg-primary-800",i="text-primary-800 dark:text-primary-100";break;case"office":t=y,s="bg-yellow-100 dark:bg-yellow-800",i="text-yellow-800 dark:text-yellow-100";break;default:t=y,s="bg-gray-100 dark:bg-gray-800",i="text-gray-800 dark:text-gray-100"}return a.jsxs("span",{className:`flex items-center gap-1 px-3 py-1 rounded-xl font-medium ${s} ${i}`,children:[a.jsx(t,{className:"w-4 h-4"}),l(e.name)]},e.id)}))})]})]})},U=()=>{const{id:d}=N();return d?a.jsx(L,{id:d}):a.jsx("div",{className:"text-gray-900 dark:text-gray-100",children:"Organization ID is missing"})};export{U as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{f as B,i as D,u as H,r as n,j as s,I as y,B as N,s as O,t as b}from"./index-7T7TTikv.js";import{L as v}from"./lock-DGEqses-.js";import{E as C}from"./eye-off-AoIvdwmO.js";import{E as P}from"./eye-DYwZYJcQ.js";import{R as T}from"./refresh-cw-B7fipPS4.js";import{A as U}from"./arrow-left-mae9HpSL.js";const J=()=>{const p=B(),[u]=D(),{t:e}=H(),r=u.get("email")||"",c=u.get("verificationCode")||"",i=u.get("userId")||"",[t,S]=n.useState(""),[d,E]=n.useState(""),[f,w]=n.useState(!1),[g,a]=n.useState(""),[x,L]=n.useState(!1),[h,R]=n.useState(!1);n.useEffect(()=>{!i&&!r&&a("Missing required parameters in the reset link. Please request a new password reset link."),c||a("Missing verification code in the reset link. Please request a new password reset link.")},[i,r,c]);const k=async m=>{if(m.preventDefault(),a(""),!t){a(e("msg.newPasswordRequired"));return}if(t.length<8){a(e("msg.passwordMinLength"));return}if(!d){a(e("msg.confirmPasswordRequired"));return}if(t!==d){a(e("msg.passwordMismatch"));return}const q=/[A-Z]/.test(t),I=/[a-z]/.test(t),M=/\d/.test(t),A=/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(t),l=[];if(q||l.push(e("msg.uppercaseLetter")),I||l.push(e("msg.lowercaseLetter")),M||l.push(e("msg.number")),A||l.push(e("msg.specialCharacter")),l.length>0){a(e("msg.passwordComplexity")+" "+l.join(", "));return}w(!0);try{const o={verificationCode:c,newPassword:t,confirmPassword:d};i&&(o.userId=i),r&&(o.email=r),await O(o),b.success(e("msg.successChange"),{description:e("msg.passwordResetSuccess")}),setTimeout(()=>p("/"),2e3)}catch(o){const j=(o==null?void 0:o.message)||e("msg.failedChange");a(j),b.error(e("msg.failedChange"),{description:j})}finally{w(!1)}};return s.jsx("div",{className:"min-h-screen bg-gray-100 p-4 flex items-center justify-center",children:s.jsxs("div",{className:"w-full max-w-md bg-white rounded-xl shadow-lg p-6 md:p-8",children:[s.jsxs("div",{className:"mb-6 md:mb-8 text-center",children:[s.jsx("img",{src:"/assets/smart-office-logo.svg",alt:"Smart Office Logo",className:"h-8 md:h-10 mb-4 md:mb-6 mx-auto"}),s.jsx("h1",{className:"text-xl md:text-2xl font-bold text-gray-900 mb-2",children:"Reset Password"}),s.jsx("p",{className:"text-xs md:text-sm text-gray-500",children:"Set a new password for your account"}),r&&s.jsxs("p",{className:"text-xs text-gray-400 mt-1 truncate max-w-full px-2",children:["Email: ",r]}),i&&s.jsxs("p",{className:"text-xs text-gray-400 mt-1 truncate max-w-full px-2",children:["User ID: ",i]})]}),s.jsxs("form",{onSubmit:k,className:"space-y-4 md:space-y-6",children:[s.jsxs("div",{className:"space-y-3",children:[s.jsxs("div",{className:"relative",children:[s.jsx("div",{className:"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none",children:s.jsx(v,{className:"h-4 w-4 md:h-5 md:w-5 text-gray-400"})}),s.jsx(y,{type:x?"text":"password",placeholder:"New Password",className:"h-10 rounded-md border px-4 text-sm ps-10 pr-10",value:t,onChange:m=>S(m.target.value),required:!0}),s.jsx("button",{type:"button",className:"absolute inset-y-0 right-0 pr-3 flex items-center",onClick:()=>L(!x),"aria-label":x?"Hide password":"Show password",children:x?s.jsx(C,{className:"h-4 w-4 text-gray-400"}):s.jsx(P,{className:"h-4 w-4 text-gray-400"})})]}),s.jsxs("div",{className:"relative",children:[s.jsx("div",{className:"absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none",children:s.jsx(v,{className:"h-4 w-4 md:h-5 md:w-5 text-gray-400"})}),s.jsx(y,{type:h?"text":"password",placeholder:"Confirm New Password",className:"h-10 rounded-md border px-4 text-sm ps-10 pr-10",value:d,onChange:m=>E(m.target.value),required:!0}),s.jsx("button",{type:"button",className:"absolute inset-y-0 right-0 pr-3 flex items-center",onClick:()=>R(!h),"aria-label":h?"Hide password":"Show password",children:h?s.jsx(C,{className:"h-4 w-4 text-gray-400"}):s.jsx(P,{className:"h-4 w-4 text-gray-400"})})]}),g&&s.jsx("div",{className:"bg-red-50 border border-red-200 rounded-md p-3 md:p-4",children:s.jsx("p",{className:"text-xs md:text-sm text-red-700 font-medium",children:g})})]}),s.jsxs("div",{className:"flex flex-col gap-3",children:[s.jsx(N,{type:"submit",className:"w-full h-10 bg-primary hover:bg-primary-300 text-white text-sm",disabled:f||!i&&!r||!c,children:f?s.jsxs("span",{className:"flex items-center justify-center",children:[s.jsx(T,{className:"animate-spin h-4 w-4 md:h-5 md:w-5 mr-2"}),"Resetting..."]}):"Reset Password"}),s.jsxs(N,{type:"button",variant:"outline",className:"w-full h-10 text-sm",onClick:()=>p("/"),children:[s.jsx(U,{className:"h-4 w-4 mr-2"}),"Back to Login"]})]})]})]})})};export{J as ResetPassword,J as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{K as S,N as x,V as h,j as f,Q as N,W as R,Y as g,X as a}from"./index-7T7TTikv.js";var l={root:"m_18320242","skeleton-fade":"m_299c329c"};const j={visible:!0,animate:!0},_=R((r,{width:o,height:s,radius:e,circle:t})=>({root:{"--skeleton-height":a(s),"--skeleton-width":t?a(s):a(o),"--skeleton-radius":t?"1000px":e===void 0?void 0:g(e)}})),n=S((r,o)=>{const s=x("Skeleton",j,r),{classNames:e,className:t,style:i,styles:c,unstyled:m,vars:d,width:b,height:w,circle:P,visible:u,radius:V,animate:p,mod:v,...k}=s,y=h({name:"Skeleton",classes:l,props:s,className:t,style:i,classNames:e,styles:c,unstyled:m,vars:d,varsResolver:_});return f.jsx(N,{ref:o,...y("root"),mod:[{visible:u,animate:p},v],...k})});n.classes=l;n.displayName="@mantine/core/Skeleton";export{n as S};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{r as n,az as g,u as y,n as v,j as i}from"./index-7T7TTikv.js";import{A as j}from"./AdvancedTable-vWyUWUDX.js";import{C as A,a as C,b,d as N}from"./card-_ldW-koX.js";import{u as S,A as U}from"./ArchivedUserColumnDefn-Ja27QDEy.js";import{f as I}from"./organizationService-B_C-b9EH.js";import{S as z}from"./FormFields-DeF71qnl.js";import"./table-D_B7hhqb.js";import"./select--i8koVXg.js";import"./chevron-left-G_a9-f9o.js";import"./utils-N2wtfq7C.js";import"./badge-D4t6Wb1T.js";import"./command-B6S1IvD4.js";import"./search-y8VSu0lZ.js";import"./popover-CSKEA8hg.js";import"./Popover-BSKEfTKH.js";import"./use-uncontrolled-tg0LIUAX.js";import"./separator-BXi_hr72.js";import"./refresh-cw-B7fipPS4.js";import"./organizationsService-DIFVjoLn.js";import"./alert-dialog-DwppaTz4.js";import"./useEmployeePostions-BZG3u-zs.js";import"./employeePositionsService-C7MSoCNC.js";import"./ellipsis-vertical-CoMd89ns.js";import"./square-pen-Dh1zj83N.js";import"./user-plus-tzUBEFtH.js";import"./form-lLGtsTgY.js";import"./index.esm-BRNlF2G3.js";import"./label-CABYEcfW.js";import"./multi-select-CZLBnGmP.js";import"./single-select-CqAjmX3L.js";const ne=()=>{const[o,c]=n.useState(0),p=g(),{t:m}=y(),{data:t,isLoading:u,error:E}=v({queryKey:["organizations"],queryFn:I,staleTime:300*1e3}),[s,d]=n.useState(null),f=e=>{d(e)},h=n.useMemo(()=>(t==null?void 0:t.items.map(e=>({id:e.id,name:e.name,hierarchyType:"organization",value:e.units.length===1?e.units[0].id:"",children:Array.isArray(e.units)&&e.units.length>0?e.units.map(r=>({id:r.id,name:r.name,hierarchyType:"unit",value:r.id,children:[]})):[]})))||[],[t,p]);n.useEffect(()=>{if(!s&&(t!=null&&t.items)){const e=t.items.flatMap(r=>r.units).find(r=>r.id);e&&d(e.id)}},[t,s]),n.useEffect(()=>{s&&sessionStorage.setItem("selectedArchiveUnitId",s)},[s]),n.useEffect(()=>{const e=sessionStorage.getItem("selectedArchiveUnitId");e&&d(e)},[]);const{data:a,refetch:x}=S(s??""),l=e=>{c(e)};return u?i.jsx("div",{className:"text-gray-900 dark:text-gray-100",children:m("loading")}):i.jsx("div",{className:"p-6 space-y-6",children:i.jsxs(A,{className:"col-span-2 shadow-none border-none bg-transparent px-0",children:[i.jsx(C,{className:"flex flex-row justify-between items-center px-0",children:i.jsx(b,{className:"text-xl font-semibold",children:m("setting.archivedUsers")})}),i.jsx("div",{className:"mb-4",children:i.jsx(z,{label:m("selectUnit"),options:h,value:s,onChange:f,collapsible:!0})}),i.jsx(N,{className:"px-0",children:i.jsx(j,{columns:U,data:(a==null?void 0:a.items)||[],tableName:"Archived Users",toolBarPosition:"right",itemCount:(a==null?void 0:a.count)||0,pageIndex:o,onPageChange:l,nextFunction:()=>l(o+1),prevFunction:()=>l(Math.max(o-1,0)),refresh:x})})]})})};export{ne as default};

View File

@@ -0,0 +1,6 @@
import{y as O,u as w,az as S,r as c,j as e,B as l,A as I}from"./index-7T7TTikv.js";import{C as M,a as U,b as T,d as B}from"./card-_ldW-koX.js";import{S as P,a as R,b as F,c as K,d as L}from"./select--i8koVXg.js";import{A as v}from"./AdvancedTable-vWyUWUDX.js";import{u as E}from"./useOrganizations-CPt4mkXS.js";import{c as H,a as V,u as _}from"./useArchived-5V0W60Gf.js";import{A as f}from"./archive-restore-CbEMfc7_.js";import"./table-D_B7hhqb.js";import"./chevron-left-G_a9-f9o.js";import"./utils-N2wtfq7C.js";import"./badge-D4t6Wb1T.js";import"./command-B6S1IvD4.js";import"./search-y8VSu0lZ.js";import"./popover-CSKEA8hg.js";import"./Popover-BSKEfTKH.js";import"./use-uncontrolled-tg0LIUAX.js";import"./separator-BXi_hr72.js";import"./refresh-cw-B7fipPS4.js";import"./organizationsService-DIFVjoLn.js";import"./unitService-DTtkt-Pb.js";import"./positionService-BwPU5sNe.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const q=[["path",{d:"M10 18v-7",key:"wt116b"}],["path",{d:"M11.12 2.198a2 2 0 0 1 1.76.006l7.866 3.847c.476.233.31.949-.22.949H3.474c-.53 0-.695-.716-.22-.949z",key:"1m329m"}],["path",{d:"M14 18v-7",key:"vav6t3"}],["path",{d:"M18 18v-7",key:"aexdmj"}],["path",{d:"M3 22h18",key:"8prr45"}],["path",{d:"M6 18v-7",key:"1ivflk"}]],G=O("landmark",q),ge=()=>{const{t:a}=w(),m=S(),[t,g]=c.useState("organizations"),{organizationsResponse:d}=E("Org",{take:300,skip:0}),o=(d==null?void 0:d.items)??[],[h,p]=c.useState("");!h&&o.length>0&&p(o[0].id);const{data:s,refetch:j}=H(),{data:n,refetch:z}=V(t==="units"&&h||void 0),u=c.useMemo(()=>(s==null?void 0:s.items)??s??[],[s]),x=c.useMemo(()=>(n==null?void 0:n.items)??n??[],[n]),{restoreUnit:y,isRestoringUnit:k,restoreOrganization:N,isRestoringOrganization:A}=_(),b=[{id:"name",header:a("organization.name","Name"),cell:({row:i})=>{var r;return m((r=i.original)==null?void 0:r.name)||"—"}},{id:"key",header:a("organization.key","Key"),accessorKey:"key"},{id:"actions",header:a("userIncomingretun.Actions","Actions"),cell:({row:i})=>e.jsxs(l,{size:"sm",variant:"outline",disabled:A,onClick:()=>N(i.original.id),className:"flex items-center gap-2 text-primary-700 hover:bg-primary-50",children:[e.jsx(f,{className:"h-4 w-4"}),a("archive.restore","Restore")]})}],C=[{id:"name",header:a("organization.name","Name"),cell:({row:i})=>{var r;return m((r=i.original)==null?void 0:r.name)||"—"}},{id:"key",header:a("organization.key","Key"),accessorKey:"key"},{id:"actions",header:a("userIncomingretun.Actions","Actions"),cell:({row:i})=>e.jsxs(l,{size:"sm",variant:"outline",disabled:k,onClick:()=>y(i.original.id),className:"flex items-center gap-2 text-primary-700 hover:bg-primary-50",children:[e.jsx(f,{className:"h-4 w-4"}),a("archive.restore","Restore")]})}];return e.jsx("div",{className:"p-6 space-y-6",children:e.jsxs(M,{className:"shadow-none border-none bg-transparent px-0",children:[e.jsx(U,{className:"flex flex-row justify-between items-center px-0",children:e.jsx(T,{className:"text-xl font-semibold",children:a("archive.archivedItems","Archived Items")})}),e.jsxs("div",{className:"flex gap-2 mb-4",children:[e.jsxs(l,{variant:t==="organizations"?"default":"outline",onClick:()=>g("organizations"),className:"flex items-center gap-2",children:[e.jsx(G,{className:"h-4 w-4"}),a("archive.archivedOrganizations","Archived Organizations")]}),e.jsxs(l,{variant:t==="units"?"default":"outline",onClick:()=>g("units"),className:"flex items-center gap-2",children:[e.jsx(I,{className:"h-4 w-4"}),a("archive.archivedUnits","Archived Units")]})]}),t==="units"&&o.length>0&&e.jsxs("div",{className:"mb-4 w-full sm:w-1/2",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 dark:text-gray-200",children:a("organization.selectOrganization","Select Organization")}),e.jsxs(P,{value:h,onValueChange:i=>p(i),children:[e.jsx(R,{className:"mt-1 block w-full",children:e.jsx(F,{placeholder:a("organization.selectOrganization")})}),e.jsx(K,{children:o.map(i=>e.jsx(L,{value:i.id,children:m(i.name)},i.id))})]})]}),e.jsx(B,{className:"px-0",children:t==="organizations"?e.jsx(v,{columns:b,data:u,tableName:"ArchivedOrganizations",toolBarPosition:"right",itemCount:u.length,pageIndex:0,onPageChange:()=>{},nextFunction:()=>{},prevFunction:()=>{},refresh:j}):e.jsx(v,{columns:C,data:x,tableName:"ArchivedUnits",toolBarPosition:"right",itemCount:x.length,pageIndex:0,onPageChange:()=>{},nextFunction:()=>{},prevFunction:()=>{},refresh:z})})]})})};export{ge as default};

View File

@@ -0,0 +1 @@
import{r as R,K as L,N as T,j as s,ae as W,V as X,au as Z,a8 as ee,Q as N,W as te,aa as se,_ as h,Y as ae}from"./index-7T7TTikv.js";import{I as oe,a as ce,b as re}from"./InputsGroupFieldset-B16dMH0P.js";import{u as A}from"./use-uncontrolled-tg0LIUAX.js";const B=R.createContext(null),le=B.Provider,ne=()=>R.useContext(B),ie={},x=L((l,o)=>{const{value:t,defaultValue:e,onChange:b,size:d,wrapperProps:u,children:p,readOnly:f,...y}=T("SwitchGroup",ie,l),[c,m]=A({value:t,defaultValue:e,finalValue:[],onChange:b}),w=v=>{const n=v.currentTarget.value;!f&&m(c.includes(n)?c.filter(C=>C!==n):[...c,n])};return s.jsx(le,{value:{value:c,onChange:w,size:d},children:s.jsx(W.Wrapper,{size:d,ref:o,...u,...y,labelElement:"div",__staticSelector:"SwitchGroup",children:s.jsx(oe,{role:"group",children:p})})})});x.classes=W.Wrapper.classes;x.displayName="@mantine/core/SwitchGroup";var F={root:"m_5f93f3bb",input:"m_926b4011",track:"m_9307d992",thumb:"m_93039a1d",trackLabel:"m_8277e082"};const he={labelPosition:"right"},de=te((l,{radius:o,color:t,size:e})=>({root:{"--switch-radius":o===void 0?void 0:ae(o),"--switch-height":h(e,"switch-height"),"--switch-width":h(e,"switch-width"),"--switch-thumb-size":h(e,"switch-thumb-size"),"--switch-label-font-size":h(e,"switch-label-font-size"),"--switch-track-label-padding":h(e,"switch-track-label-padding"),"--switch-color":t?se(t,l):void 0}})),_=L((l,o)=>{const t=T("Switch",he,l),{classNames:e,className:b,style:d,styles:u,unstyled:p,vars:f,color:y,label:c,offLabel:m,onLabel:w,id:v,size:n,radius:C,wrapperProps:K,thumbIcon:O,checked:g,defaultChecked:Q,onChange:S,labelPosition:P,description:U,error:j,disabled:G,variant:Y,rootRef:$,mod:q,...D}=t,a=ne(),H=n||(a==null?void 0:a.size),i=X({name:"Switch",props:t,classes:F,className:b,style:d,classNames:e,styles:u,unstyled:p,vars:f,varsResolver:de}),{styleProps:J,rest:I}=Z(D),V=ee(v),r=a?{checked:a.value.includes(I.value),onChange:a.onChange}:{},[z,M]=A({value:r.checked??g,defaultValue:Q,finalValue:!1});return s.jsxs(ce,{...i("root"),__staticSelector:"Switch",__stylesApiProps:t,id:V,size:H,labelPosition:P,label:c,description:U,error:j,disabled:G,bodyElement:"label",labelElement:"span",classNames:e,styles:u,unstyled:p,"data-checked":r.checked||g||void 0,variant:Y,ref:$,mod:q,...J,...K,children:[s.jsx("input",{...I,disabled:G,checked:z,"data-checked":r.checked||g||void 0,onChange:k=>{var E;a?(E=r.onChange)==null||E.call(r,k):S==null||S(k),M(k.currentTarget.checked)},id:V,ref:o,type:"checkbox",role:"switch",...i("input")}),s.jsxs(N,{"aria-hidden":"true",component:"span",mod:{error:j,"label-position":P,"without-labels":!w&&!m},...i("track"),children:[s.jsx(N,{component:"span",mod:"reduce-motion",...i("thumb"),children:O}),s.jsx("span",{...i("trackLabel"),children:z?w:m})]})]})});_.classes={...F,...re};_.displayName="@mantine/core/Switch";_.Group=x;export{_ as S};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{r as a,j as s,b8 as l,bv as i}from"./index-7T7TTikv.js";const o=i("relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",{variants:{variant:{default:"bg-background text-foreground",destructive:"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"}},defaultVariants:{variant:"default"}}),n=a.forwardRef(({className:e,variant:t,...r},d)=>s.jsx("div",{ref:d,role:"alert",className:l(o({variant:t}),e),...r}));n.displayName="Alert";const v=a.forwardRef(({className:e,...t},r)=>s.jsx("h5",{ref:r,className:l("mb-1 font-medium leading-none tracking-tight",e),...t}));v.displayName="AlertTitle";const c=a.forwardRef(({className:e,...t},r)=>s.jsx("div",{ref:r,className:l("text-sm [&_p]:leading-relaxed",e),...t}));c.displayName="AlertDescription";export{n as A,c as a,v as b};

View File

@@ -0,0 +1 @@
import{r,j as a,b1 as p,b8 as i,b9 as x}from"./index-7T7TTikv.js";const u=r.createContext({open:!1,setOpen:()=>{}});function b({children:e,open:t,onOpenChange:s,defaultOpen:l=!1}){const[o,n]=r.useState(l),c=t!==void 0,f=c?t:o,g=r.useCallback(d=>{c||n(d),s==null||s(d)},[c,s]);return a.jsx(u.Provider,{value:{open:f,setOpen:g},children:e})}function j({children:e,asChild:t}){const{setOpen:s}=r.useContext(u);return t&&r.isValidElement(e)?r.cloneElement(e,{onClick:l=>{var o,n;(n=(o=e.props).onClick)==null||n.call(o,l),s(!0)}}):a.jsx("span",{"data-slot":"alert-dialog-trigger",onClick:()=>s(!0),style:{display:"contents",cursor:"pointer"},children:e})}function A({children:e,className:t,...s}){const{open:l,setOpen:o}=r.useContext(u);return a.jsx(p,{opened:l,onClose:()=>o(!1),withCloseButton:!1,centered:!0,padding:0,radius:"lg",classNames:{content:i("bg-background text-foreground",t),overlay:"bg-black/50"},...s,children:a.jsx("div",{className:"grid gap-4 p-6",children:e})})}function v({className:e,...t}){return a.jsx("div",{"data-slot":"alert-dialog-header",className:i("flex flex-col gap-2 text-center sm:text-left",e),...t})}function D({className:e,...t}){return a.jsx("div",{"data-slot":"alert-dialog-footer",className:i("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",e),...t})}function N({className:e,...t}){return a.jsx("div",{"data-slot":"alert-dialog-title",className:i("text-lg font-semibold",e),...t})}function y({className:e,...t}){return a.jsx("div",{"data-slot":"alert-dialog-description",className:i("text-muted-foreground text-sm",e),...t})}function C({className:e,onClick:t,children:s,...l}){const{setOpen:o}=r.useContext(u);return a.jsx("button",{type:"button",className:i(x(),e),onClick:n=>{t==null||t(n),o(!1)},...l,children:s})}function E({className:e,onClick:t,children:s,...l}){const{setOpen:o}=r.useContext(u);return a.jsx("button",{type:"button",className:i(x({variant:"outline"}),e),onClick:n=>{t==null||t(n),o(!1)},...l,children:s})}export{b as A,A as a,v as b,N as c,y as d,D as e,E as f,C as g,j as h};

View File

@@ -0,0 +1,6 @@
import{y as e}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const t=[["rect",{width:"20",height:"5",x:"2",y:"3",rx:"1",key:"1wp1u1"}],["path",{d:"M4 8v11a2 2 0 0 0 2 2h2",key:"tvwodi"}],["path",{d:"M20 8v11a2 2 0 0 1-2 2h-2",key:"1gkqxj"}],["path",{d:"m9 15 3-3 3 3",key:"1pd0qc"}],["path",{d:"M12 12v9",key:"192myk"}]],o=e("archive-restore",t);export{o as A};

View File

@@ -0,0 +1,6 @@
import{y as o}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const e=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],r=o("arrow-left",e);export{r as A};

View File

@@ -0,0 +1 @@
import{r as p,K as M,N,V as b,j as c,Q as j,W as w,a3 as Z,$ as z,Y as F,_ as V,b8 as $}from"./index-7T7TTikv.js";const G=p.createContext(null),P=G.Provider;function B(){return{withinGroup:!!p.useContext(G)}}var C={group:"m_11def92b",root:"m_f85678b6",image:"m_11f8ac07",placeholder:"m_104cd71f"};const U={},K=w((r,{spacing:a})=>({group:{"--ag-spacing":Z(a)}})),h=M((r,a)=>{const t=N("AvatarGroup",U,r),{classNames:e,className:n,style:l,styles:u,unstyled:i,vars:d,spacing:s,...o}=t,m=b({name:"AvatarGroup",classes:C,props:t,className:n,style:l,classNames:e,styles:u,unstyled:i,vars:d,varsResolver:K,rootSelector:"group"});return c.jsx(P,{value:!0,children:c.jsx(j,{ref:a,...m("group"),...o})})});h.classes=C;h.displayName="@mantine/core/AvatarGroup";function Q(r){return c.jsx("svg",{...r,"data-avatar-placeholder-icon":!0,viewBox:"0 0 15 15",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:c.jsx("path",{d:"M0.877014 7.49988C0.877014 3.84219 3.84216 0.877045 7.49985 0.877045C11.1575 0.877045 14.1227 3.84219 14.1227 7.49988C14.1227 11.1575 11.1575 14.1227 7.49985 14.1227C3.84216 14.1227 0.877014 11.1575 0.877014 7.49988ZM7.49985 1.82704C4.36683 1.82704 1.82701 4.36686 1.82701 7.49988C1.82701 8.97196 2.38774 10.3131 3.30727 11.3213C4.19074 9.94119 5.73818 9.02499 7.50023 9.02499C9.26206 9.02499 10.8093 9.94097 11.6929 11.3208C12.6121 10.3127 13.1727 8.97172 13.1727 7.49988C13.1727 4.36686 10.6328 1.82704 7.49985 1.82704ZM10.9818 11.9787C10.2839 10.7795 8.9857 9.97499 7.50023 9.97499C6.01458 9.97499 4.71624 10.7797 4.01845 11.9791C4.97952 12.7272 6.18765 13.1727 7.49985 13.1727C8.81227 13.1727 10.0206 12.727 10.9818 11.9787ZM5.14999 6.50487C5.14999 5.207 6.20212 4.15487 7.49999 4.15487C8.79786 4.15487 9.84999 5.207 9.84999 6.50487C9.84999 7.80274 8.79786 8.85487 7.49999 8.85487C6.20212 8.85487 5.14999 7.80274 5.14999 6.50487ZM7.49999 5.10487C6.72679 5.10487 6.09999 5.73167 6.09999 6.50487C6.09999 7.27807 6.72679 7.90487 7.49999 7.90487C8.27319 7.90487 8.89999 7.27807 8.89999 6.50487C8.89999 5.73167 8.27319 5.10487 7.49999 5.10487Z",fill:"currentColor",fillRule:"evenodd",clipRule:"evenodd"})})}function W(r){let a=0;for(let t=0;t<r.length;t+=1){const e=r.charCodeAt(t);a=(a<<5)-a+e,a|=0}return a}const Y=["blue","cyan","grape","green","indigo","lime","orange","pink","red","teal","violet"];function q(r,a=Y){const t=W(r),e=Math.abs(t)%a.length;return a[e]}function D(r,a=2){const t=r.split(" ");return t.length===1?r.slice(0,a).toUpperCase():t.map(e=>e[0]).slice(0,a).join("").toUpperCase()}const H={},J=w((r,{size:a,radius:t,variant:e,gradient:n,color:l,autoContrast:u,name:i,allowedInitialsColors:d})=>{const s=l==="initials"&&typeof i=="string"?q(i,d):l,o=r.variantColorResolver({color:s||"gray",theme:r,gradient:n,variant:e||"light",autoContrast:u});return{root:{"--avatar-size":V(a,"avatar-size"),"--avatar-radius":t===void 0?void 0:F(t),"--avatar-bg":s||e?o.background:void 0,"--avatar-color":s||e?o.color:void 0,"--avatar-bd":s||e?o.border:void 0}}}),g=z((r,a)=>{const t=N("Avatar",H,r),{classNames:e,className:n,style:l,styles:u,unstyled:i,vars:d,src:s,alt:o,radius:m,color:X,gradient:aa,imageProps:v,children:R,autoContrast:ra,mod:E,name:x,allowedInitialsColors:ta,...I}=t,S=B(),[_,y]=p.useState(!s),f=b({name:"Avatar",props:t,classes:C,className:n,style:l,classNames:e,styles:u,unstyled:i,vars:d,varsResolver:J});return p.useEffect(()=>y(!s),[s]),c.jsx(j,{...f("root"),mod:[{"within-group":S.withinGroup},E],ref:a,...I,children:_?c.jsx("span",{...f("placeholder"),title:o,children:R||typeof x=="string"&&D(x)||c.jsx(Q,{})}):c.jsx("img",{...v,...f("image"),src:s,alt:o,onError:k=>{var A;y(!0),(A=v==null?void 0:v.onError)==null||A.call(v,k)}})})});g.classes=C;g.displayName="@mantine/core/Avatar";g.Group=h;p.createContext({});function L({className:r,children:a,...t}){const e=p.Children.toArray(a),n=e.find(s=>{var o;return p.isValidElement(s)&&((o=s.type)==null?void 0:o.displayName)==="AvatarImage"}),l=e.find(s=>{var o;return p.isValidElement(s)&&((o=s.type)==null?void 0:o.displayName)==="AvatarFallback"}),u=n==null?void 0:n.props.src,i=(n==null?void 0:n.props.alt)??"",d=l==null?void 0:l.props.children;return c.jsx(g,{src:u,alt:i,radius:"xl",className:$("relative flex size-8 shrink-0 overflow-hidden rounded-full",r),...t,children:d})}L.displayName="Avatar";function O({className:r,src:a,alt:t,...e}){return null}O.displayName="AvatarImage";function T({className:r,children:a,...t}){return null}T.displayName="AvatarFallback";export{L as A,T as a,g as b,O as c};

View File

@@ -0,0 +1 @@
import{r as d,b8 as a,j as g,bv as u}from"./index-7T7TTikv.js";const o=u("inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",{variants:{variant:{default:"bg-blue-100 text-blue-800 text-sm font-medium me-2 px-3 py-0.5 rounded-full dark:bg-blue-900 dark:text-blue-300",secondary:"bg-indigo-100 text-indigo-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-indigo-900 dark:text-indigo-300",destructive:"bg-gray-100 text-gray-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-sm dark:bg-gray-700 dark:text-gray-300",outline:"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",info:"border-transparent bg-info text-info-foreground [a&]:hover:bg-info/90",purple:"bg-purple-100 text-purple-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-purple-900 dark:text-purple-300",warning:"bg-pink-100 text-pink-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-pink-900 dark:text-pink-300",success:"bg-green-100 text-green-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-green-900 dark:text-green-300",danger:"bg-red-100 text-red-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-red-900 dark:text-red-300",danger2:"bg-yellow-100 text-yellow-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-yellow-900 dark:text-yellow-300",forward:"bg-orange-100 text-orange-800 text-sm font-medium me-2 px-3 py-0.5 rounded-full dark:bg-orange-900 dark:text-orange-300",dispatched:"bg-green-100 text-green-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-green-900 dark:text-green-300"}},defaultVariants:{variant:"default"}});function l({className:t,variant:r,asChild:i=!1,children:e,...n}){return i&&d.isValidElement(e)?d.cloneElement(e,{className:a(o({variant:r}),e.props.className,t),...n}):g.jsx("span",{"data-slot":"badge",className:a(o({variant:r}),t),...n,children:e})}export{l as B};

View File

@@ -0,0 +1,6 @@
import{y as h}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const t=[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2",key:"76otgf"}],["path",{d:"M9 22v-4h6v4",key:"r93iot"}],["path",{d:"M8 6h.01",key:"1dz90k"}],["path",{d:"M16 6h.01",key:"1x0f13"}],["path",{d:"M12 6h.01",key:"1vi96p"}],["path",{d:"M12 10h.01",key:"1nrarc"}],["path",{d:"M12 14h.01",key:"1etili"}],["path",{d:"M16 10h.01",key:"1m94wz"}],["path",{d:"M16 14h.01",key:"1gbofw"}],["path",{d:"M8 10h.01",key:"19clt8"}],["path",{d:"M8 14h.01",key:"6423bh"}]],d=h("building",t);export{d as B};

View File

@@ -0,0 +1 @@
import{j as e,b8 as r}from"./index-7T7TTikv.js";function s({className:a,...t}){return e.jsx("div",{"data-slot":"card",className:r("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",a),...t})}function n({className:a,...t}){return e.jsx("div",{"data-slot":"card-header",className:r("flex flex-col gap-1.5 px-6",a),...t})}function o({className:a,...t}){return e.jsx("div",{"data-slot":"card-title",className:r("leading-none font-semibold",a),...t})}function c({className:a,...t}){return e.jsx("div",{"data-slot":"card-description",className:r("text-muted-foreground text-sm",a),...t})}function l({className:a,...t}){return e.jsx("div",{"data-slot":"card-content",className:r("px-6",a),...t})}export{s as C,n as a,o as b,c,l as d};

View File

@@ -0,0 +1 @@
import{j as l,b8 as b,bv as d}from"./index-7T7TTikv.js";import{a as o}from"./Checkbox-CAXGYFGh.js";const c=d("",{variants:{variant:{default:"",subtle:"border-muted bg-muted/20",soft:"rounded-full border-2 border-primary"},size:{sm:"!w-3 !h-3",md:"!w-4 !h-4",lg:"!w-5 !h-5"}},defaultVariants:{variant:"default",size:"md"}});function n({className:i,variant:m="default",size:u="md",checked:s,onCheckedChange:t,disabled:e,...f}){const r=s==="indeterminate";return l.jsx(o,{checked:r?!1:s??!1,indeterminate:r,onChange:a=>{t==null||t(a.currentTarget.checked)},disabled:e,classNames:{input:b(c({variant:m,size:u}),i)},...f})}export{n as C};

View File

@@ -0,0 +1,6 @@
import{y as e}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const o=[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]],c=e("chevron-left",o);export{c as C};

View File

@@ -0,0 +1,6 @@
import{y as e}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const c=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],y=e("circle-alert",c);export{y as C};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
import{y as o}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const a=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],e=o("download",a);export{e as D};

View File

@@ -0,0 +1 @@
import{f as C,d as A,az as k,r as o,j as e,v as i,I as u,B as w,bj as T}from"./index-7T7TTikv.js";import{C as z,a as E,b as M,d as B}from"./card-_ldW-koX.js";import{L as t}from"./label-CABYEcfW.js";import{S as O,a as V,b as F,c as H,d as K}from"./select--i8koVXg.js";import{u as U}from"./useUnit-CRt6YBLp.js";import{u as q,P as D,p as G}from"./useApplications-Czki0Urb.js";import{u as J}from"./usePositionTypes-BnS1UB0m.js";import"./unitService-DTtkt-Pb.js";import"./checkbox-CTVlz2xL.js";import"./Checkbox-CAXGYFGh.js";import"./get-auto-contrast-value-Da6zqqWm.js";import"./InputsGroupFieldset-B16dMH0P.js";import"./use-uncontrolled-tg0LIUAX.js";import"./form-lLGtsTgY.js";import"./index.esm-BRNlF2G3.js";import"./search-y8VSu0lZ.js";const Q=({id:r})=>{var h,j;const y=C(),{user:n}=A(),{getList:v}=U(),x=k(),{positionType:a,isLoadingSingle:f}=J({id:r}),N=n!=null&&n.employee&&n.employee.length>0?n.employee[0].organizationId:void 0,{applications:d,isLoading:P}=q(),{data:l}=v(N||"",{take:300,skip:0}),[c,b]=o.useState(""),[m,S]=o.useState([]),[I,g]=o.useState(!1);if(o.useEffect(()=>{(async()=>{if(a){g(!0);try{const L=await G.getPermissionsByPositionTypeId(a.id);S(L.data.items??[])}finally{g(!1)}}})()},[a]),f)return e.jsx("p",{children:"Loading..."});if(!a)return null;const p=(j=(h=l==null?void 0:l.data)==null?void 0:h.items)==null?void 0:j.find(s=>s.id===a.unitId);return p?p.name.en||p.name.am:a.unitId,e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(t,{children:i("contentManagement.englishName")}),e.jsx(u,{value:a.name.en,disabled:!0,readOnly:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(t,{children:i("contentManagement.amharicName")}),e.jsx(u,{value:a.name.am,disabled:!0,readOnly:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(t,{children:"Key"}),e.jsx(u,{value:a.key,disabled:!0,readOnly:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(t,{children:i("contentManagement.selectApplication")}),e.jsxs(O,{value:c,onValueChange:s=>b(s),disabled:P,children:[e.jsx(V,{className:"mt-1 block w-full border-gray-300 rounded-md shadow-sm",children:e.jsx(F,{placeholder:"Select an Application"})}),e.jsx(H,{className:"max-h-60 overflow-y-auto",children:d==null?void 0:d.map(s=>e.jsx(K,{value:s.id,children:x(s.name)},s.id))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(t,{children:i("contentManagement.permission")}),c?e.jsx(D,{selectedPermissions:m.map(s=>s.id),onPermissionChange:()=>{},applicationId:c,disabled:!0}):e.jsx("div",{className:"border rounded-md p-4 bg-background max-h-96 overflow-y-auto",children:I?e.jsx("div",{className:"text-center py-4 text-gray-500",children:"Loading..."}):m.length===0?e.jsx("div",{className:"text-center py-4 text-gray-500",children:i("contentManagement.noPermissionsAvailable")}):e.jsx("ul",{className:"grid grid-cols-1 md:grid-cols-2 gap-2",children:m.map(s=>e.jsx("li",{className:"capitalize text-sm py-1 px-2 rounded bg-muted/40",children:x(s.name)},s.id))})})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(w,{type:"button",variant:"outline",onClick:()=>y("/user-management/position-management"),children:i("common.Back")})})]})},le=()=>{const{id:r}=T();return e.jsx("div",{className:"p-6 max-w-3xl mx-auto",children:e.jsxs(z,{children:[e.jsx(E,{children:e.jsx(M,{children:"View Permission Type"})}),e.jsx(B,{children:e.jsx(Q,{id:r})})]})})};export{le as default};

View File

@@ -0,0 +1,6 @@
import{y as c}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const e=[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"19",cy:"12",r:"1",key:"1wjl8i"}],["circle",{cx:"5",cy:"12",r:"1",key:"1pcz8c"}]],r=c("ellipsis",e);export{r as E};

View File

@@ -0,0 +1,6 @@
import{y as c}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const e=[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"12",cy:"5",r:"1",key:"gxeob9"}],["circle",{cx:"12",cy:"19",r:"1",key:"lyex9k"}]],r=c("ellipsis-vertical",e);export{r as E};

View File

@@ -0,0 +1 @@
import{l as e,w as o}from"./index-7T7TTikv.js";const n=async s=>e.post("/employee-positions/invite",s,{headers:o()}),i=async s=>e.post("/employee-positions/inactive",s,{headers:o()}),r=async(s,t)=>e.get(`/employee-positions/given-first/${s}`,{headers:o(),params:t}),c=async(s,t)=>e.get(`/employee-positions/given-second/${s}`,{headers:o(),params:t}),p=async(s,t)=>e.patch(`/users/update-users-profile/${t}`,s),d=async(s,t)=>e.patch(`/users/update-users-profile/${t}`,s),y=async s=>e.post("/employee-positions/assign",s,{headers:o()}),l=async s=>e.post("/employee-positions/assign-firsts-for-second",s,{headers:o()}),m=async s=>e.post("/employee-positions/assign-seconds-for-first",s,{headers:o()}),h=async s=>e.delete(`/employee-positions/${s}`,{headers:o()}),v=async s=>e.post("/employee-positions/remove-firsts-for-second",s,{headers:o()}),f=async s=>e.post("/employee-positions/remove-seconds-for-first",s,{headers:o()}),g=async s=>e.patch(`/employees/${s}/deactivate`,{headers:o()}),u=async s=>e.patch(`/employees/${s}/activate`,{headers:o()});export{d as a,u as b,l as c,g as d,m as e,y as f,f as g,h,n as i,r as j,c as k,v as r,i as s,p as u};

View File

@@ -0,0 +1,6 @@
import{y as c}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const e=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],r=c("eye",e);export{r as E};

View File

@@ -0,0 +1,6 @@
import{y as e}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const a=[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],t=e("eye-off",a);export{t as E};

View File

@@ -0,0 +1 @@
import{r as a,j as n,b8 as d}from"./index-7T7TTikv.js";import{F as u,C as x,b as F,c as b}from"./index.esm-BRNlF2G3.js";import{L as I}from"./label-CABYEcfW.js";const p=u,l=a.createContext({}),j=({...e})=>n.jsx(l.Provider,{value:{name:e.name},children:n.jsx(x,{...e})}),c=()=>{const e=a.useContext(l),r=a.useContext(f),{getFieldState:t}=F(),o=b({name:e.name}),s=t(e.name,o);if(!e)throw new Error("useFormField should be used within <FormField>");const{id:i}=r;return{id:i,name:e.name,formItemId:`${i}-form-item`,formDescriptionId:`${i}-form-item-description`,formMessageId:`${i}-form-item-message`,...s}},f=a.createContext({});function h({className:e,...r}){const t=a.useId();return n.jsx(f.Provider,{value:{id:t},children:n.jsx("div",{"data-slot":"form-item",className:d("grid gap-2",e),...r})})}function y({className:e,...r}){const{error:t,formItemId:o}=c();return n.jsx(I,{"data-slot":"form-label","data-error":!!t,className:d("data-[error=true]:text-destructive-foreground",e),htmlFor:o,...r})}function E({children:e,...r}){const{error:t,formItemId:o,formDescriptionId:s,formMessageId:i}=c(),m={id:o,"aria-describedby":t?`${s} ${i}`:s,"aria-invalid":!!t,...r};return a.isValidElement(e)?a.cloneElement(e,{...m,...e.props,id:o,"aria-describedby":m["aria-describedby"],"aria-invalid":m["aria-invalid"]}):n.jsx("div",{"data-slot":"form-control",...m,children:e})}function S({className:e,...r}){const{error:t,formMessageId:o}=c(),s=t?String((t==null?void 0:t.message)??""):r.children;return s?n.jsx("p",{"data-slot":"form-message",id:o,className:d("text-destructive-foreground text-sm",e),...r,children:s}):null}export{p as F,j as a,h as b,y as c,E as d,S as e};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{j as t,b8 as o}from"./index-7T7TTikv.js";function n({className:e,...a}){return t.jsx("label",{"data-slot":"label",className:o("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",e),...a})}export{n as L};

View File

@@ -0,0 +1,6 @@
import{y as a}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const e=[["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m16.2 7.8 2.9-2.9",key:"r700ao"}],["path",{d:"M18 12h4",key:"wj9ykh"}],["path",{d:"m16.2 16.2 2.9 2.9",key:"1bxg5t"}],["path",{d:"M12 18v4",key:"jadmvz"}],["path",{d:"m4.9 19.1 2.9-2.9",key:"bwix9q"}],["path",{d:"M2 12h4",key:"j09sii"}],["path",{d:"m4.9 4.9 2.9 2.9",key:"giyufr"}]],d=a("loader",e);export{d as L};

View File

@@ -0,0 +1,6 @@
import{y as e}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const o=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],t=e("lock",o);export{t as L};

View File

@@ -0,0 +1,6 @@
import{y as e}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const o=[["path",{d:"m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7",key:"132q7q"}],["rect",{x:"2",y:"4",width:"20",height:"16",rx:"2",key:"izxlao"}]],a=e("mail",o);export{a as M};

View File

@@ -0,0 +1,6 @@
import{y as e}from"./index-7T7TTikv.js";/**
* @license lucide-react v0.513.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const a=[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",key:"1lielz"}]],o=e("message-square",a);export{o as M};

Some files were not shown because too many files have changed in this diff Show More