From ac23d47b791b82f030d034d47117543ba4911cfc Mon Sep 17 00:00:00 2001 From: ahasani194 Date: Thu, 16 Apr 2026 22:19:46 +0330 Subject: [PATCH] update license structures and init to setup image uploader --- docker-compose.yml | 80 +++++++++---------- .../consumers/components/form.component.ts | 8 +- .../modules/consumers/models/io.d.ts | 13 ++- .../modules/consumers/models/licenses_io.d.ts | 4 +- .../modules/consumers/views/list.component.ts | 4 +- .../consumers/views/single.component.html | 2 +- .../consumers/views/single.component.ts | 10 ++- .../guilds/components/goods/list.component.ts | 2 +- .../charge-license-form-dialog.component.html | 8 +- .../charge-license-form-dialog.component.ts | 29 ++++--- .../list.component.html | 11 +++ .../list.component.ts | 42 ++++++++++ .../partners/components/form.component.html | 7 -- .../partners/components/form.component.ts | 1 - .../components/licenses/list.component.html | 4 +- .../components/licenses/list.component.ts | 8 +- .../{licenses.ts => activatedLicenses.ts} | 4 +- .../apiRoutes/chargeLicenseTransactions.ts | 6 ++ .../partners/constants/apiRoutes/index.ts | 2 + ...nses_io.d.ts => activatedLicenses_io.d.ts} | 5 +- .../models/chargeLicenseTransactions_io.d.ts | 13 +++ .../modules/partners/models/index.ts | 3 +- .../modules/partners/models/io.d.ts | 17 ++-- .../chargeLicenseTransactions.service.ts | 35 ++++++++ .../partners/services/licenses.service.ts | 12 +-- .../modules/partners/services/main.service.ts | 16 +--- .../partners/views/list.component.html | 13 ++- .../modules/partners/views/list.component.ts | 8 +- .../partners/views/single.component.html | 51 ++++++++---- .../partners/views/single.component.ts | 2 + .../page-data-list.component.html | 11 ++- .../pageDataList/page-data-list.component.ts | 41 +++++++++- .../shared/components/uploadFile/model.d.ts | 4 + .../uploadFile/upload-file.component.html | 8 ++ .../uploadFile/upload-file.component.ts | 31 +++++++ .../uikit/datepicker/datepicker.component.ts | 6 +- 36 files changed, 379 insertions(+), 142 deletions(-) create mode 100644 src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.html create mode 100644 src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.ts rename src/app/domains/superAdmin/modules/partners/constants/apiRoutes/{licenses.ts => activatedLicenses.ts} (58%) create mode 100644 src/app/domains/superAdmin/modules/partners/constants/apiRoutes/chargeLicenseTransactions.ts rename src/app/domains/superAdmin/modules/partners/models/{licenses_io.d.ts => activatedLicenses_io.d.ts} (50%) create mode 100644 src/app/domains/superAdmin/modules/partners/models/chargeLicenseTransactions_io.d.ts create mode 100644 src/app/domains/superAdmin/modules/partners/services/chargeLicenseTransactions.service.ts create mode 100644 src/app/shared/components/uploadFile/model.d.ts create mode 100644 src/app/shared/components/uploadFile/upload-file.component.html create mode 100644 src/app/shared/components/uploadFile/upload-file.component.ts diff --git a/docker-compose.yml b/docker-compose.yml index b3c91df..d808622 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,47 +23,47 @@ services: - psp_panel_network # Staging service - staging: - build: - context: . - dockerfile: Dockerfile.staging - container_name: psp_panel_staging - ports: - - "5050:5000" - environment: - - NODE_ENV=staging - restart: unless-stopped - healthcheck: - test: - ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"] - interval: 30s - timeout: 3s - retries: 3 - start_period: 5s - profiles: - - staging - networks: - - psp_panel_network + # staging: + # build: + # context: . + # dockerfile: Dockerfile.staging + # container_name: psp_panel_staging + # ports: + # - "5050:5000" + # environment: + # - NODE_ENV=staging + # restart: unless-stopped + # healthcheck: + # test: + # ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"] + # interval: 30s + # timeout: 3s + # retries: 3 + # start_period: 5s + # profiles: + # - staging + # networks: + # - psp_panel_network - # Development service with hot reload - dev: - build: - context: . - dockerfile: Dockerfile.dev - container_name: psp_panel-dev - working_dir: /app - volumes: - - .:/app - - /app/node_modules - ports: - - "4200:4200" - environment: - - NODE_ENV=development - restart: unless-stopped - profiles: - - dev - networks: - - psp_panel_network + # # Development service with hot reload + # dev: + # build: + # context: . + # dockerfile: Dockerfile.dev + # container_name: psp_panel-dev + # working_dir: /app + # volumes: + # - .:/app + # - /app/node_modules + # ports: + # - "4200:4200" + # environment: + # - NODE_ENV=development + # restart: unless-stopped + # profiles: + # - dev + # networks: + # - psp_panel_network networks: psp_panel_network: diff --git a/src/app/domains/superAdmin/modules/consumers/components/form.component.ts b/src/app/domains/superAdmin/modules/consumers/components/form.component.ts index 511c85b..9ddc796 100644 --- a/src/app/domains/superAdmin/modules/consumers/components/form.component.ts +++ b/src/app/domains/superAdmin/modules/consumers/components/form.component.ts @@ -48,8 +48,8 @@ export class ConsumerUserFormComponent extends AbstractFormDialog< password: [''], confirmPassword: [''], license: this.fb.group({ - starts_at: [this.initialValues?.license?.starts_at || ''], - partner_id: [this.initialValues?.license?.partner?.id || ''], + starts_at: [this.initialValues?.license_info?.starts_at || ''], + partner_id: [this.initialValues?.license_info?.partner?.id || ''], }), }); @@ -95,8 +95,8 @@ export class ConsumerUserFormComponent extends AbstractFormDialog< this.form.patchValue({ ...(this.initialValues ?? {}), license: { - ...(this.initialValues?.license ?? {}), - partner_id: this.initialValues?.license?.partner?.id || '', + ...(this.initialValues?.license_info ?? {}), + partner_id: this.initialValues?.license_info?.partner?.id || '', }, }); if (this.editMode && !this.consumerId) { diff --git a/src/app/domains/superAdmin/modules/consumers/models/io.d.ts b/src/app/domains/superAdmin/modules/consumers/models/io.d.ts index 17c67a6..68a2be2 100644 --- a/src/app/domains/superAdmin/modules/consumers/models/io.d.ts +++ b/src/app/domains/superAdmin/modules/consumers/models/io.d.ts @@ -1,4 +1,4 @@ -import { ILicenseRawResponse, ILicenseRequest } from './licenses_io'; +import ISummary from '@/core/models/summary'; export interface IConsumerRawResponse { id: string; @@ -6,8 +6,9 @@ export interface IConsumerRawResponse { last_name: string; mobile_number: string; status: string; + created_at: string; fullname: string; - license: ILicenseRawResponse; + license_info: ILicenseInfo; } export interface IConsumerResponse extends IConsumerRawResponse {} @@ -17,5 +18,11 @@ export interface IConsumerRequest { mobile_number: string; username: string; password: string; - license?: ILicenseRequest; +} + +interface ILicenseInfo { + id: string; + starts_at: string; + expires_at: string; + partner: ISummary; } diff --git a/src/app/domains/superAdmin/modules/consumers/models/licenses_io.d.ts b/src/app/domains/superAdmin/modules/consumers/models/licenses_io.d.ts index 044cc02..48b8389 100644 --- a/src/app/domains/superAdmin/modules/consumers/models/licenses_io.d.ts +++ b/src/app/domains/superAdmin/modules/consumers/models/licenses_io.d.ts @@ -4,7 +4,7 @@ export interface ILicenseRawResponse { id: string; starts_at: string; expires_at: string; - status: TLicenseStatus; + // status: TLicenseStatus; partner?: ISummary; } export interface ILicenseResponse extends ILicenseRawResponse {} @@ -12,6 +12,6 @@ export interface ILicenseResponse extends ILicenseRawResponse {} export interface ILicenseRequest { starts_at: string; expires_at?: string; - status: TLicenseStatus; + // status: TLicenseStatus; partner_id: string; } diff --git a/src/app/domains/superAdmin/modules/consumers/views/list.component.ts b/src/app/domains/superAdmin/modules/consumers/views/list.component.ts index 95453bd..db53ad9 100644 --- a/src/app/domains/superAdmin/modules/consumers/views/list.component.ts +++ b/src/app/domains/superAdmin/modules/consumers/views/list.component.ts @@ -28,8 +28,8 @@ export class ConsumersComponent extends AbstractList { field: 'license_expires_at', header: 'تاریخ انقضای لایسنس', customDataModel(item) { - if (item.license) { - return formatJalali(item.license.expires_at); + if (item.license_info) { + return formatJalali(item.license_info.expires_at); } return 'بدون لایسنس'; }, diff --git a/src/app/domains/superAdmin/modules/consumers/views/single.component.html b/src/app/domains/superAdmin/modules/consumers/views/single.component.html index ba2f4b2..90d5c84 100644 --- a/src/app/domains/superAdmin/modules/consumers/views/single.component.html +++ b/src/app/domains/superAdmin/modules/consumers/views/single.component.html @@ -42,7 +42,7 @@ this.store.loading()); readonly consumer = computed(() => this.store.entity()); - readonly license = computed(() => this.store.entity()?.license); + readonly license = computed(() => this.store.entity()?.license_info); readonly licenseStatus = computed(() => { - if (!this.store.entity()?.license?.expires_at) { + console.log(this.store.entity()?.license_info?.expires_at); + + if (!this.store.entity()?.license_info?.expires_at) { return null; } - if (new Date().getTime() > new Date(this.store.entity()?.license?.expires_at || '').getTime()) { + if ( + new Date().getTime() > new Date(this.store.entity()?.license_info?.expires_at || '').getTime() + ) { return licenseStatus.EXPIRED; } return licenseStatus.ACTIVE; diff --git a/src/app/domains/superAdmin/modules/guilds/components/goods/list.component.ts b/src/app/domains/superAdmin/modules/guilds/components/goods/list.component.ts index bf022af..aa58f1a 100644 --- a/src/app/domains/superAdmin/modules/guilds/components/goods/list.component.ts +++ b/src/app/domains/superAdmin/modules/guilds/components/goods/list.component.ts @@ -18,7 +18,7 @@ export class GuildGoodsListComponent extends AbstractList { @Input() guildId!: string; @Input() fullHeight?: boolean; @Input() header: IColumn[] = [ - { field: 'id', header: 'شناسه', type: 'id' }, + { field: 'image_url', header: 'تصویر', type: 'thumbnail' }, { field: 'name', header: 'عنوان' }, { field: 'sku', header: 'شناسه‌ی عمومی' }, { field: 'category', header: 'دسته‌بندی', type: 'nested', nestedPath: 'category.name' }, diff --git a/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.html b/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.html index 3540cd0..2c43221 100644 --- a/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.html +++ b/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.html @@ -7,7 +7,13 @@ (onHide)="close()" >
- + + diff --git a/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.ts b/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.ts index 0761ab8..1e6ba68 100644 --- a/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.ts +++ b/src/app/domains/superAdmin/modules/partners/components/charge-license-form-dialog.component.ts @@ -1,30 +1,41 @@ import { AbstractFormDialog } from '@/shared/abstractClasses'; import { InputComponent } from '@/shared/components'; import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component'; +import { UikitFlatpickrJalaliComponent } from '@/uikit'; +import { nowJalali } from '@/utils'; import { Component, inject, Input } from '@angular/core'; import { ReactiveFormsModule, Validators } from '@angular/forms'; import { Dialog } from 'primeng/dialog'; -import { ILicenseChargeRequest, ILicenseChargeResponse } from '../models'; -import { PartnersService } from '../services/main.service'; +import { IPartnerChargeLicenseTransactionRequest } from '../models/chargeLicenseTransactions_io'; +import { AdminPartnerChargeLicenseTransactionsService } from '../services/chargeLicenseTransactions.service'; @Component({ selector: 'partner-charge-license-form-dialog', templateUrl: './charge-license-form-dialog.component.html', - imports: [Dialog, ReactiveFormsModule, InputComponent, FormFooterActionsComponent], + imports: [ + Dialog, + ReactiveFormsModule, + InputComponent, + FormFooterActionsComponent, + UikitFlatpickrJalaliComponent, + ], }) export class PartnerChargeLicenseFormDialogComponent extends AbstractFormDialog< - ILicenseChargeRequest, - ILicenseChargeResponse + IPartnerChargeLicenseTransactionRequest, + any > { @Input({ required: true }) partnerId!: string; - private readonly service = inject(PartnersService); + private readonly service = inject(AdminPartnerChargeLicenseTransactionsService); form = this.fb.group({ - count: [0, [Validators.min(0)]], + quantity: [0, [Validators.required, Validators.min(1)]], + activated_expires_at: ['', [Validators.required]], }); - submitForm(payload: ILicenseChargeRequest) { - return this.service.licenseCharge(this.partnerId, payload); + minDate = nowJalali(); + + submitForm(payload: IPartnerChargeLicenseTransactionRequest) { + return this.service.charge(this.partnerId, payload); } } diff --git a/src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.html b/src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.html new file mode 100644 index 0000000..e3f4efe --- /dev/null +++ b/src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.html @@ -0,0 +1,11 @@ + + + diff --git a/src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.ts b/src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.ts new file mode 100644 index 0000000..eb2ce43 --- /dev/null +++ b/src/app/domains/superAdmin/modules/partners/components/chargeLicenseTransactions/list.component.ts @@ -0,0 +1,42 @@ +// import { CatalogRoleTagComponent } from '@/shared/catalog/roles'; +import { AbstractList } from '@/shared/abstractClasses/abstract-list'; +import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component'; +import { Component, inject, Input } from '@angular/core'; +import { IPartnerChargeLicenseTransactionRawResponse } from '../../models'; +import { AdminPartnerChargeLicenseTransactionsService } from '../../services/chargeLicenseTransactions.service'; + +@Component({ + selector: 'admin-partner-chargeLicenseTransaction-list', + templateUrl: './list.component.html', + imports: [PageDataListComponent], +}) +export class AdminPartnerChargeLicenseTransactionListComponent extends AbstractList { + @Input({ required: true }) partnerId!: string; + + private readonly service = inject(AdminPartnerChargeLicenseTransactionsService); + + override setColumns(): void { + this.columns = [ + { field: 'id', header: 'شناسه', type: 'id' }, + { field: 'charged_license_count', header: 'تعداد لایسنس خریداری شده' }, + { field: 'remained_license_count', header: 'تعداد لایسنس فروخته نشده' }, + { + field: 'activation_expires_at', + header: 'تاریخ انقضا', + type: 'date', + dateOption: { + expiredMode: true, + }, + }, + { + field: 'created_at', + header: 'تاریخ ایجاد', + type: 'date', + }, + ]; + } + + override getDataRequest() { + return this.service.getAll(this.partnerId); + } +} diff --git a/src/app/domains/superAdmin/modules/partners/components/form.component.html b/src/app/domains/superAdmin/modules/partners/components/form.component.html index b0b353b..5ca97fd 100644 --- a/src/app/domains/superAdmin/modules/partners/components/form.component.html +++ b/src/app/domains/superAdmin/modules/partners/components/form.component.html @@ -9,13 +9,6 @@
- @if (!editMode) { اطلاعات ورود diff --git a/src/app/domains/superAdmin/modules/partners/components/form.component.ts b/src/app/domains/superAdmin/modules/partners/components/form.component.ts index 1f2929e..ea3bd2e 100644 --- a/src/app/domains/superAdmin/modules/partners/components/form.component.ts +++ b/src/app/domains/superAdmin/modules/partners/components/form.component.ts @@ -32,7 +32,6 @@ export class GuildFormComponent extends AbstractFormDialog diff --git a/src/app/domains/superAdmin/modules/partners/components/licenses/list.component.ts b/src/app/domains/superAdmin/modules/partners/components/licenses/list.component.ts index 618dd67..2a20d39 100644 --- a/src/app/domains/superAdmin/modules/partners/components/licenses/list.component.ts +++ b/src/app/domains/superAdmin/modules/partners/components/licenses/list.component.ts @@ -2,18 +2,18 @@ import { AbstractList } from '@/shared/abstractClasses/abstract-list'; import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component'; import { Component, inject, Input } from '@angular/core'; -import { IPartnerLicenseResponse } from '../../models'; -import { AdminPartnerLicensesService } from '../../services/licenses.service'; +import { IPartnerActivatedLicenseResponse } from '../../models'; +import { AdminPartnerActivatedLicensesService } from '../../services/licenses.service'; @Component({ selector: 'admin-partner-licenses', templateUrl: './list.component.html', imports: [PageDataListComponent], }) -export class AdminPartnerLicensesComponent extends AbstractList { +export class AdminPartnerLicensesComponent extends AbstractList { @Input({ required: true }) partnerId!: string; - private readonly service = inject(AdminPartnerLicensesService); + private readonly service = inject(AdminPartnerActivatedLicensesService); override setColumns(): void { this.columns = [ diff --git a/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/licenses.ts b/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/activatedLicenses.ts similarity index 58% rename from src/app/domains/superAdmin/modules/partners/constants/apiRoutes/licenses.ts rename to src/app/domains/superAdmin/modules/partners/constants/apiRoutes/activatedLicenses.ts index be7811b..d038feb 100644 --- a/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/licenses.ts +++ b/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/activatedLicenses.ts @@ -1,5 +1,5 @@ -const baseUrl = (partnerId: string) => `/api/v1/admin/partners/${partnerId}/licenses`; +const baseUrl = (partnerId: string) => `/api/v1/admin/partners/${partnerId}/activated-licenses`; -export const PARTNER_LICENSES_API_ROUTES = { +export const PARTNER_ACTIVATED_LICENSES_API_ROUTES = { list: (partnerId: string) => `${baseUrl(partnerId)}`, }; diff --git a/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/chargeLicenseTransactions.ts b/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/chargeLicenseTransactions.ts new file mode 100644 index 0000000..7042bc4 --- /dev/null +++ b/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/chargeLicenseTransactions.ts @@ -0,0 +1,6 @@ +const baseUrl = (partnerId: string) => + `/api/v1/admin/partners/${partnerId}/charge-license-transactions`; + +export const PARTNER_CHARGE_LICENSE_TRANSACTIONS_API_ROUTES = { + list: (partnerId: string) => `${baseUrl(partnerId)}`, +}; diff --git a/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/index.ts b/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/index.ts index fb27d84..9afbefd 100644 --- a/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/index.ts +++ b/src/app/domains/superAdmin/modules/partners/constants/apiRoutes/index.ts @@ -1,4 +1,6 @@ export * from './accounts'; +export * from './activatedLicenses'; +export * from './chargeLicenseTransactions'; const baseUrl = '/api/v1/admin/partners'; diff --git a/src/app/domains/superAdmin/modules/partners/models/licenses_io.d.ts b/src/app/domains/superAdmin/modules/partners/models/activatedLicenses_io.d.ts similarity index 50% rename from src/app/domains/superAdmin/modules/partners/models/licenses_io.d.ts rename to src/app/domains/superAdmin/modules/partners/models/activatedLicenses_io.d.ts index 6408f22..0a2e23a 100644 --- a/src/app/domains/superAdmin/modules/partners/models/licenses_io.d.ts +++ b/src/app/domains/superAdmin/modules/partners/models/activatedLicenses_io.d.ts @@ -1,12 +1,11 @@ -export interface IPartnerLicenseRawResponse { +export interface IPartnerActivatedLicenseRawResponse { id: string; starts_at: string; expires_at: string; - status: TLicenseStatus; consumer: { first_name: string; last_name: string; mobile_number: string; }; } -export interface IPartnerLicenseResponse extends IPartnerLicenseRawResponse {} +export interface IPartnerActivatedLicenseResponse extends IPartnerActivatedLicenseRawResponse {} diff --git a/src/app/domains/superAdmin/modules/partners/models/chargeLicenseTransactions_io.d.ts b/src/app/domains/superAdmin/modules/partners/models/chargeLicenseTransactions_io.d.ts new file mode 100644 index 0000000..5047906 --- /dev/null +++ b/src/app/domains/superAdmin/modules/partners/models/chargeLicenseTransactions_io.d.ts @@ -0,0 +1,13 @@ +export interface IPartnerChargeLicenseTransactionRawResponse { + id: string; + created_at: string; + activation_expires_at: string; + charged_license_count: number; + remained_license_count: number; +} +export interface IPartnerChargeLicenseTransactionResponse extends IPartnerChargeLicenseTransactionRawResponse {} + +export interface IPartnerChargeLicenseTransactionRequest { + quantity: number; + activated_expires_at: string; +} diff --git a/src/app/domains/superAdmin/modules/partners/models/index.ts b/src/app/domains/superAdmin/modules/partners/models/index.ts index 5954d6e..2a352fb 100644 --- a/src/app/domains/superAdmin/modules/partners/models/index.ts +++ b/src/app/domains/superAdmin/modules/partners/models/index.ts @@ -1,3 +1,4 @@ export * from './accounts_io'; +export * from './activatedLicenses_io'; +export * from './chargeLicenseTransactions_io'; export * from './io'; -export * from './licenses_io'; diff --git a/src/app/domains/superAdmin/modules/partners/models/io.d.ts b/src/app/domains/superAdmin/modules/partners/models/io.d.ts index 0644b73..d62470d 100644 --- a/src/app/domains/superAdmin/modules/partners/models/io.d.ts +++ b/src/app/domains/superAdmin/modules/partners/models/io.d.ts @@ -2,8 +2,13 @@ export interface IPartnerRawResponse { id: string; name: string; code: string; - remained_license: number; - license_quota: number; + status: string; + created_at: string; + licenses_status: { + total: number; + used: number; + expired: number; + }; } export interface IPartnerResponse extends IPartnerRawResponse {} @@ -12,11 +17,3 @@ export interface IPartnerRequest { code: string; license_quota: number; } - -//charge license -export interface ILicenseChargeRawResponse {} -export interface ILicenseChargeResponse extends ILicenseChargeRawResponse {} - -export interface ILicenseChargeRequest { - count: number; -} diff --git a/src/app/domains/superAdmin/modules/partners/services/chargeLicenseTransactions.service.ts b/src/app/domains/superAdmin/modules/partners/services/chargeLicenseTransactions.service.ts new file mode 100644 index 0000000..e42de4c --- /dev/null +++ b/src/app/domains/superAdmin/modules/partners/services/chargeLicenseTransactions.service.ts @@ -0,0 +1,35 @@ +import { IPaginatedResponse } from '@/core/models/service.model'; +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { PARTNER_CHARGE_LICENSE_TRANSACTIONS_API_ROUTES } from '../constants'; +import { + IPartnerChargeLicenseTransactionRawResponse, + IPartnerChargeLicenseTransactionRequest, + IPartnerChargeLicenseTransactionResponse, +} from '../models'; + +@Injectable({ providedIn: 'root' }) +export class AdminPartnerChargeLicenseTransactionsService { + constructor(private http: HttpClient) {} + + private apiRoutes = PARTNER_CHARGE_LICENSE_TRANSACTIONS_API_ROUTES; + + getAll( + partnerId: string, + ): Observable> { + return this.http.get>( + this.apiRoutes.list(partnerId), + ); + } + + charge( + partnerId: string, + data: IPartnerChargeLicenseTransactionRequest, + ): Observable { + return this.http.post( + this.apiRoutes.list(partnerId), + data, + ); + } +} diff --git a/src/app/domains/superAdmin/modules/partners/services/licenses.service.ts b/src/app/domains/superAdmin/modules/partners/services/licenses.service.ts index d4b21bf..b54c333 100644 --- a/src/app/domains/superAdmin/modules/partners/services/licenses.service.ts +++ b/src/app/domains/superAdmin/modules/partners/services/licenses.service.ts @@ -2,17 +2,17 @@ import { IPaginatedResponse } from '@/core/models/service.model'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { PARTNER_LICENSES_API_ROUTES } from '../constants/apiRoutes/licenses'; -import { IPartnerLicenseRawResponse, IPartnerLicenseResponse } from '../models'; +import { PARTNER_ACTIVATED_LICENSES_API_ROUTES } from '../constants/apiRoutes/activatedLicenses'; +import { IPartnerActivatedLicenseRawResponse, IPartnerActivatedLicenseResponse } from '../models'; @Injectable({ providedIn: 'root' }) -export class AdminPartnerLicensesService { +export class AdminPartnerActivatedLicensesService { constructor(private http: HttpClient) {} - private apiRoutes = PARTNER_LICENSES_API_ROUTES; + private apiRoutes = PARTNER_ACTIVATED_LICENSES_API_ROUTES; - getAll(partnerId: string): Observable> { - return this.http.get>( + getAll(partnerId: string): Observable> { + return this.http.get>( this.apiRoutes.list(partnerId), ); } diff --git a/src/app/domains/superAdmin/modules/partners/services/main.service.ts b/src/app/domains/superAdmin/modules/partners/services/main.service.ts index 6f84a77..b857af7 100644 --- a/src/app/domains/superAdmin/modules/partners/services/main.service.ts +++ b/src/app/domains/superAdmin/modules/partners/services/main.service.ts @@ -3,14 +3,7 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { PARTNERS_API_ROUTES } from '../constants'; -import { - ILicenseChargeRawResponse, - ILicenseChargeRequest, - ILicenseChargeResponse, - IPartnerRawResponse, - IPartnerRequest, - IPartnerResponse, -} from '../models'; +import { IPartnerRawResponse, IPartnerRequest, IPartnerResponse } from '../models'; @Injectable({ providedIn: 'root' }) export class PartnersService { @@ -32,11 +25,4 @@ export class PartnersService { update(partnerId: string, userData: IPartnerRequest): Observable { return this.http.patch(this.apiRoutes.single(partnerId), userData); } - - licenseCharge( - partnerId: string, - data: ILicenseChargeRequest, - ): Observable { - return this.http.post(this.apiRoutes.licenseCharge(partnerId), data); - } } diff --git a/src/app/domains/superAdmin/modules/partners/views/list.component.html b/src/app/domains/superAdmin/modules/partners/views/list.component.html index 8590e30..c9e37de 100644 --- a/src/app/domains/superAdmin/modules/partners/views/list.component.html +++ b/src/app/domains/superAdmin/modules/partners/views/list.component.html @@ -13,7 +13,18 @@ (onAdd)="openAddForm()" (onDetails)="toSinglePage($event)" (onEdit)="onEditClick($event)" -/> +> + + + {{ item.licenses_status.total }} + @if (item.licenses_status.used) { + ({{ item.licenses_status.used }} عدد استفاده شده) + } @else { + (تمامی لایسنس‌ها فعال می‌باشند) + } + + + { private readonly service = inject(PartnersService); private readonly router = inject(Router); + @ViewChild('licensesStatus', { static: true }) licensesStatus!: TemplateRef; + override setColumns(): void { this.columns = [ - { field: 'id', header: 'شناسه', type: 'id' }, { field: 'name', header: 'نام' }, { field: 'code', header: 'کد' }, - { field: 'license_quota', header: 'تعداد لایسنس خریداری شده' }, + { field: 'licenses', header: 'وضعیت لایسنس‌ها', customDataModel: this.licensesStatus }, + { field: 'status', header: 'وضعیت' }, { field: 'created_at', header: 'تاریخ ایجاد', diff --git a/src/app/domains/superAdmin/modules/partners/views/single.component.html b/src/app/domains/superAdmin/modules/partners/views/single.component.html index e497d60..a4ba9ca 100644 --- a/src/app/domains/superAdmin/modules/partners/views/single.component.html +++ b/src/app/domains/superAdmin/modules/partners/views/single.component.html @@ -7,27 +7,44 @@
- - + + + +
- +
+ +
- +
+ +
- - - +
+ +
+ + + + diff --git a/src/app/domains/superAdmin/modules/partners/views/single.component.ts b/src/app/domains/superAdmin/modules/partners/views/single.component.ts index 0fce13c..6a49f67 100644 --- a/src/app/domains/superAdmin/modules/partners/views/single.component.ts +++ b/src/app/domains/superAdmin/modules/partners/views/single.component.ts @@ -5,6 +5,7 @@ import { ActivatedRoute } from '@angular/router'; import { Button } from 'primeng/button'; import { ConsumerAccountListComponent } from '../components/accounts/list.component'; import { PartnerChargeLicenseFormDialogComponent } from '../components/charge-license-form-dialog.component'; +import { AdminPartnerChargeLicenseTransactionListComponent } from '../components/chargeLicenseTransactions/list.component'; import { GuildFormComponent } from '../components/form.component'; import { AdminPartnerLicensesComponent } from '../components/licenses/list.component'; import { superAdminPartnersNamedRoutes } from '../constants'; @@ -21,6 +22,7 @@ import { PartnerStore } from '../store/partner.store'; Button, PartnerChargeLicenseFormDialogComponent, AdminPartnerLicensesComponent, + AdminPartnerChargeLicenseTransactionListComponent, ], }) export class PartnerComponent { diff --git a/src/app/shared/components/pageDataList/page-data-list.component.html b/src/app/shared/components/pageDataList/page-data-list.component.html index e684c17..5e6615f 100644 --- a/src/app/shared/components/pageDataList/page-data-list.component.html +++ b/src/app/shared/components/pageDataList/page-data-list.component.html @@ -64,6 +64,15 @@ @if (col.type === "index") { {{ i * (currentPage || 1) + 1 }} + } @else if (col.type === "thumbnail") { +
+ @if (item[col.field]) { + + } +
} @else if (getTemplate(col)) { } @else { - + {{ getCell(item, col) }} } diff --git a/src/app/shared/components/pageDataList/page-data-list.component.ts b/src/app/shared/components/pageDataList/page-data-list.component.ts index 67d6299..2e82b36 100644 --- a/src/app/shared/components/pageDataList/page-data-list.component.ts +++ b/src/app/shared/components/pageDataList/page-data-list.component.ts @@ -1,5 +1,5 @@ import { PaginatorComponent, UikitCopyComponent, UikitEmptyStateComponent } from '@/uikit'; -import { formatJalali, formatWithCurrency } from '@/utils'; +import { formatJalali, formatWithCurrency, jalaliDiff } from '@/utils'; import { CommonModule } from '@angular/common'; import { Component, @@ -26,8 +26,18 @@ export interface IColumn { width?: string; minWidth?: string; canCopy?: boolean; - type?: 'text' | 'price' | 'boolean' | 'date' | 'nested' | 'index' | 'id'; + type?: 'text' | 'price' | 'boolean' | 'date' | 'nested' | 'index' | 'id' | 'thumbnail'; nestedPath?: string; + thumbnailOptions?: { + editable: boolean; + deletable: boolean; + showPreview: boolean; + }; + dateOption?: { + expiredMode?: boolean; + dateTime?: boolean; + onlyTime?: boolean; + }; customDataModel?: TemplateRef | ((item: T) => string | number | boolean); } @@ -84,6 +94,7 @@ export class PageDataListComponent { @Output() onDetails = new EventEmitter(); @Output() onAdd = new EventEmitter(); @Output() pageChange = new EventEmitter(); + @Output() onThumbnailClick = new EventEmitter(); filterDrawerVisible = signal(false); @@ -126,10 +137,36 @@ export class PageDataListComponent { this.pageChange.emit($event); }; + openThumbnailModal = (item: I) => { + // this. + }; + get showPaginator() { return !!(this.totalRecords && this.perPage && this.totalRecords > this.perPage); } + getPreviewClasses(item: Record, column: IColumn): any { + if (!item || !column || column.customDataModel) return ''; + try { + const { field } = column; + + const data = item[String(field)]; + switch (column.type) { + case 'date': + if (column.dateOption?.expiredMode) { + if (jalaliDiff(new Date(), data) > 0) { + return 'text-error'; + } + } + return ''; + default: + return; + } + } catch (e) { + return ''; + } + } + getCell(item: Record, column: IColumn): any { if (!item || !column) return ''; try { diff --git a/src/app/shared/components/uploadFile/model.d.ts b/src/app/shared/components/uploadFile/model.d.ts new file mode 100644 index 0000000..0308646 --- /dev/null +++ b/src/app/shared/components/uploadFile/model.d.ts @@ -0,0 +1,4 @@ +export interface onSelectArgs { + data: FormData; + file: File; +} diff --git a/src/app/shared/components/uploadFile/upload-file.component.html b/src/app/shared/components/uploadFile/upload-file.component.html new file mode 100644 index 0000000..6493618 --- /dev/null +++ b/src/app/shared/components/uploadFile/upload-file.component.html @@ -0,0 +1,8 @@ + + +
+ +

فایل مورد نظر خود را در اینجا رها کنید

+
+
+
diff --git a/src/app/shared/components/uploadFile/upload-file.component.ts b/src/app/shared/components/uploadFile/upload-file.component.ts new file mode 100644 index 0000000..31c18cf --- /dev/null +++ b/src/app/shared/components/uploadFile/upload-file.component.ts @@ -0,0 +1,31 @@ +import { Maybe } from '@/core'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { FileSelectEvent, FileUpload } from 'primeng/fileupload'; +import { onSelectArgs } from './model'; + +@Component({ + selector: 'app-shared-upload-file', + templateUrl: './upload-file.component.html', + imports: [FileUpload], +}) +export class SharedUploadFileComponent { + @Input() currentImage: Maybe = null; + @Input() loading: boolean = false; + @Input() name: string = 'file'; + @Input() accept: string = 'image/*'; + @Input() maxSize: Maybe = 5 * 1024; + @Input() error: Maybe = null; + @Input() hint: Maybe = null; + + @Output() onSelect = new EventEmitter(); + + onSelectedFile($event: FileSelectEvent) { + const file = $event.files?.[0]; + if (!file) { + return; + } + const payload = new FormData(); + payload.append(this.name, file, file.name); + this.onSelect.emit({ data: payload, file }); + } +} diff --git a/src/app/uikit/datepicker/datepicker.component.ts b/src/app/uikit/datepicker/datepicker.component.ts index 4f5e1b6..b161687 100644 --- a/src/app/uikit/datepicker/datepicker.component.ts +++ b/src/app/uikit/datepicker/datepicker.component.ts @@ -12,7 +12,7 @@ import { import { FormControl, ReactiveFormsModule } from '@angular/forms'; import dayjs from 'dayjs'; import flatpickr from 'flatpickr-wrap'; -import { BaseOptions } from 'flatpickr-wrap/dist/types/options'; +import { BaseOptions, DateOption } from 'flatpickr-wrap/dist/types/options'; import { InputTextModule } from 'primeng/inputtext'; import { UikitFieldComponent } from '../uikit-field.component'; @@ -32,6 +32,8 @@ export class UikitFlatpickrJalaliComponent implements OnInit { @Input() showLabel: boolean = true; @Input() showErrors: boolean = true; @Input() hint?: string; + @Input() minDate?: DateOption; + @Input() maxDate?: DateOption; @Output() valueChange = new EventEmitter(); @@ -43,6 +45,8 @@ export class UikitFlatpickrJalaliComponent implements OnInit { this.fpInstance = flatpickr(this.wrapperRef.nativeElement, { ...this.options, locale: 'fa', + minDate: this.minDate, + maxDate: this.maxDate, altInputClass: 'p-inputtext w-full', dateFormat: 'Y-m-d', altFormat: 'Y-m-d',