feat: add showPublicScores and showPublicOpinions flags to services with plan-based access control
This commit is contained in:
@@ -67,6 +67,8 @@ export class CompaniesAdapterMongoose implements ICompaniesAdapter {
|
|||||||
|
|
||||||
fixedPostIds: { type: Array, required: false },
|
fixedPostIds: { type: Array, required: false },
|
||||||
banned: { type: Boolean, required: false, default: false },
|
banned: { type: Boolean, required: false, default: false },
|
||||||
|
showPublicScores: { type: Boolean, required: false, default: true },
|
||||||
|
showPublicOpinions: { type: Boolean, required: false, default: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
this.companyList = model<ICompanyDocument>("Company", this.schema);
|
this.companyList = model<ICompanyDocument>("Company", this.schema);
|
||||||
@@ -235,6 +237,14 @@ export class CompaniesAdapterMongoose implements ICompaniesAdapter {
|
|||||||
updateCompany.banned = data.banned;
|
updateCompany.banned = data.banned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.showPublicScores !== undefined) {
|
||||||
|
updateCompany.showPublicScores = data.showPublicScores;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.showPublicOpinions !== undefined) {
|
||||||
|
updateCompany.showPublicOpinions = data.showPublicOpinions;
|
||||||
|
}
|
||||||
|
|
||||||
updateCompany.save();
|
updateCompany.save();
|
||||||
|
|
||||||
//actualizo los campos correspondientes a la localizacion de los servicios de la organizacion.
|
//actualizo los campos correspondientes a la localizacion de los servicios de la organizacion.
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ export type UpdateCompanyParams = {
|
|||||||
onboardingStep?: number;
|
onboardingStep?: number;
|
||||||
onboardingCompleted?: boolean;
|
onboardingCompleted?: boolean;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SetCompanyFileParams = {
|
export type SetCompanyFileParams = {
|
||||||
@@ -154,6 +156,8 @@ export interface ICompany {
|
|||||||
onboardingCompleted?: boolean;
|
onboardingCompleted?: boolean;
|
||||||
fixedPostIds?: Array<string>;
|
fixedPostIds?: Array<string>;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MyOranizationsView {
|
export interface MyOranizationsView {
|
||||||
@@ -203,6 +207,8 @@ export interface MyOranizationsView {
|
|||||||
onboardingStep?: number;
|
onboardingStep?: number;
|
||||||
onboardingCompleted?: boolean;
|
onboardingCompleted?: boolean;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientOrganizationView {
|
export interface ClientOrganizationView {
|
||||||
|
|||||||
@@ -67,6 +67,17 @@ class CompaniesManager implements ICompaniesManager {
|
|||||||
this.companies = new CompaniesAdapterMongoose();
|
this.companies = new CompaniesAdapterMongoose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async validatePublicRatingFlagsPlan(ownerId: string): Promise<void> {
|
||||||
|
const { default: PlanSubscriptionsList } = await import("../PlanSubscriptions/PlanSubscriptons");
|
||||||
|
const subscription = await PlanSubscriptionsList.getSubscriptionByUser({
|
||||||
|
sessionUser: ownerId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!subscription || subscription.plan.price === 0) {
|
||||||
|
throw new Error("Esta configuración está disponible solo para planes pagos.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async toggleFixedPost(data: FixCompanyPostParams): Promise<void> {
|
public async toggleFixedPost(data: FixCompanyPostParams): Promise<void> {
|
||||||
await validateSessionUser({
|
await validateSessionUser({
|
||||||
sessionUser: data.sessionUser,
|
sessionUser: data.sessionUser,
|
||||||
@@ -489,6 +500,10 @@ class CompaniesManager implements ICompaniesManager {
|
|||||||
throw new Error(NoPermissionMessage());
|
throw new Error(NoPermissionMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.showPublicScores !== undefined || data.showPublicOpinions !== undefined) {
|
||||||
|
await this.validatePublicRatingFlagsPlan(String(companyCheck.ownerId));
|
||||||
|
}
|
||||||
|
|
||||||
let updateData = {
|
let updateData = {
|
||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
@@ -597,6 +612,8 @@ class CompaniesManager implements ICompaniesManager {
|
|||||||
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
|
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
|
||||||
onboardingStep: company.onboardingStep,
|
onboardingStep: company.onboardingStep,
|
||||||
onboardingCompleted: company.onboardingCompleted,
|
onboardingCompleted: company.onboardingCompleted,
|
||||||
|
showPublicScores: company.showPublicScores ?? true,
|
||||||
|
showPublicOpinions: company.showPublicOpinions ?? true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,6 +733,8 @@ class CompaniesManager implements ICompaniesManager {
|
|||||||
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
|
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
|
||||||
onboardingStep: company.onboardingStep,
|
onboardingStep: company.onboardingStep,
|
||||||
onboardingCompleted: company.onboardingCompleted,
|
onboardingCompleted: company.onboardingCompleted,
|
||||||
|
showPublicScores: company.showPublicScores ?? true,
|
||||||
|
showPublicOpinions: company.showPublicOpinions ?? true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,6 +805,8 @@ class CompaniesManager implements ICompaniesManager {
|
|||||||
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
|
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
|
||||||
onboardingStep: company.onboardingStep,
|
onboardingStep: company.onboardingStep,
|
||||||
onboardingCompleted: company.onboardingCompleted,
|
onboardingCompleted: company.onboardingCompleted,
|
||||||
|
showPublicScores: company.showPublicScores ?? true,
|
||||||
|
showPublicOpinions: company.showPublicOpinions ?? true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export class RatingsAdapterMongoose implements IRatingsAdapter {
|
|||||||
targetId: new Types.ObjectId(filters.targetId),
|
targetId: new Types.ObjectId(filters.targetId),
|
||||||
comment: { $regex: /\S/ },
|
comment: { $regex: /\S/ },
|
||||||
})
|
})
|
||||||
.sort({ createdAt: -1 })
|
.sort({ score: -1, createdAt: -1 })
|
||||||
.limit(filters.limit || 20)
|
.limit(filters.limit || 20)
|
||||||
.select("score comment createdAt userId")
|
.select("score comment createdAt userId")
|
||||||
.populate("userId", "firstName lastName avatar")
|
.populate("userId", "firstName lastName avatar")
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ export class ServicesAdapterMongoose implements IServicesAdapter {
|
|||||||
longitude: { type: Number, required: false, default: 0 },
|
longitude: { type: Number, required: false, default: 0 },
|
||||||
published: { type: String, required: false },
|
published: { type: String, required: false },
|
||||||
banned: { type: Boolean, required: false, default: false },
|
banned: { type: Boolean, required: false, default: false },
|
||||||
|
showPublicScores: { type: Boolean, required: false, default: true },
|
||||||
|
showPublicOpinions: { type: Boolean, required: false, default: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
this.serviceList = model<IServiceDocument>("Service", this.schema);
|
this.serviceList = model<IServiceDocument>("Service", this.schema);
|
||||||
@@ -93,6 +95,8 @@ export class ServicesAdapterMongoose implements IServicesAdapter {
|
|||||||
if (data.latitude) updateService.latitude = data.latitude;
|
if (data.latitude) updateService.latitude = data.latitude;
|
||||||
if (data.longitude) updateService.longitude = data.longitude;
|
if (data.longitude) updateService.longitude = data.longitude;
|
||||||
if (data.banned !== undefined) updateService.banned = data.banned;
|
if (data.banned !== undefined) updateService.banned = data.banned;
|
||||||
|
if (data.showPublicScores !== undefined) updateService.showPublicScores = data.showPublicScores;
|
||||||
|
if (data.showPublicOpinions !== undefined) updateService.showPublicOpinions = data.showPublicOpinions;
|
||||||
|
|
||||||
await updateService.save();
|
await updateService.save();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ export type CreateServiceParams = {
|
|||||||
latitude?: number;
|
latitude?: number;
|
||||||
longitude?: number;
|
longitude?: number;
|
||||||
sessionUser: string;
|
sessionUser: string;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateServiceParams = {
|
export type UpdateServiceParams = {
|
||||||
@@ -81,6 +83,8 @@ export type UpdateServiceParams = {
|
|||||||
longitude?: number;
|
longitude?: number;
|
||||||
sessionUser: string;
|
sessionUser: string;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PaginatePublicServicesParams = FindServicesParams & {
|
export type PaginatePublicServicesParams = FindServicesParams & {
|
||||||
@@ -155,6 +159,8 @@ export interface IService {
|
|||||||
published?: SERVICE_PUBLISHED_STATUS;
|
published?: SERVICE_PUBLISHED_STATUS;
|
||||||
discountId?: string;
|
discountId?: string;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompanyServiceView {
|
export interface CompanyServiceView {
|
||||||
@@ -176,6 +182,8 @@ export interface CompanyServiceView {
|
|||||||
fontShadowColor: string;
|
fontShadowColor: string;
|
||||||
published: SERVICE_PUBLISHED_STATUS;
|
published: SERVICE_PUBLISHED_STATUS;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores: boolean;
|
||||||
|
showPublicOpinions: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PublicServiceView {
|
export interface PublicServiceView {
|
||||||
@@ -199,6 +207,8 @@ export interface PublicServiceView {
|
|||||||
fontColor: string;
|
fontColor: string;
|
||||||
fontShadowColor: string;
|
fontShadowColor: string;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores: boolean;
|
||||||
|
showPublicOpinions: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FindServicesByCompanyParams {
|
export interface FindServicesByCompanyParams {
|
||||||
|
|||||||
@@ -46,6 +46,17 @@ class ServiceManager implements IServicesManager {
|
|||||||
this.services = new ServicesAdapterMongoose();
|
this.services = new ServicesAdapterMongoose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async validatePublicRatingFlagsPlan(ownerId: string): Promise<void> {
|
||||||
|
const { default: PlanSubscriptionsList } = await import("../PlanSubscriptions/PlanSubscriptons");
|
||||||
|
const subscription = await PlanSubscriptionsList.getSubscriptionByUser({
|
||||||
|
sessionUser: ownerId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!subscription || subscription.plan.price === 0) {
|
||||||
|
throw new Error("Esta configuración está disponible solo para planes pagos.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async setPublishedStatus(data: SetPublishedStatusParams): Promise<void> {
|
public async setPublishedStatus(data: SetPublishedStatusParams): Promise<void> {
|
||||||
const sessionUser = await UsersManager.users.findOne({
|
const sessionUser = await UsersManager.users.findOne({
|
||||||
_id: data.sessionUser,
|
_id: data.sessionUser,
|
||||||
@@ -145,6 +156,10 @@ class ServiceManager implements IServicesManager {
|
|||||||
throw new Error("Ha alcanzado el limite de servicios permitidos de acuerdo a su plan.");
|
throw new Error("Ha alcanzado el limite de servicios permitidos de acuerdo a su plan.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.showPublicScores !== undefined || data.showPublicOpinions !== undefined) {
|
||||||
|
await this.validatePublicRatingFlagsPlan(String(companyCheck.ownerId));
|
||||||
|
}
|
||||||
|
|
||||||
const newService = await this.services.create({
|
const newService = await this.services.create({
|
||||||
...data,
|
...data,
|
||||||
...{
|
...{
|
||||||
@@ -190,6 +205,10 @@ class ServiceManager implements IServicesManager {
|
|||||||
throw new Error(NoPermissionMessage());
|
throw new Error(NoPermissionMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.showPublicScores !== undefined || data.showPublicOpinions !== undefined) {
|
||||||
|
await this.validatePublicRatingFlagsPlan(String(companyCheck.ownerId));
|
||||||
|
}
|
||||||
|
|
||||||
await this.services.update(data);
|
await this.services.update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,6 +326,8 @@ class ServiceManager implements IServicesManager {
|
|||||||
service.published,
|
service.published,
|
||||||
SERVICE_PUBLISHED_STATUS.PRIVATE
|
SERVICE_PUBLISHED_STATUS.PRIVATE
|
||||||
),
|
),
|
||||||
|
showPublicScores: service.showPublicScores ?? true,
|
||||||
|
showPublicOpinions: service.showPublicOpinions ?? true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +384,8 @@ class ServiceManager implements IServicesManager {
|
|||||||
fontColor: isNull<string>(service.fontColor, defFontColor),
|
fontColor: isNull<string>(service.fontColor, defFontColor),
|
||||||
fontShadowColor: isNull<string>(service.fontShadowColor, defFontShadowColor),
|
fontShadowColor: isNull<string>(service.fontShadowColor, defFontShadowColor),
|
||||||
published: isNull<SERVICE_PUBLISHED_STATUS>(service.published, SERVICE_PUBLISHED_STATUS.PRIVATE),
|
published: isNull<SERVICE_PUBLISHED_STATUS>(service.published, SERVICE_PUBLISHED_STATUS.PRIVATE),
|
||||||
|
showPublicScores: service.showPublicScores ?? true,
|
||||||
|
showPublicOpinions: service.showPublicOpinions ?? true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,6 +509,8 @@ class ServiceManager implements IServicesManager {
|
|||||||
color: isNull<string>(service.color, defColor),
|
color: isNull<string>(service.color, defColor),
|
||||||
fontColor: isNull<string>(service.fontColor, defFontColor),
|
fontColor: isNull<string>(service.fontColor, defFontColor),
|
||||||
fontShadowColor: isNull<string>(service.fontShadowColor, defFontShadowColor),
|
fontShadowColor: isNull<string>(service.fontShadowColor, defFontShadowColor),
|
||||||
|
showPublicScores: service.showPublicScores ?? true,
|
||||||
|
showPublicOpinions: service.showPublicOpinions ?? true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ export type PublicOrganizationView = {
|
|||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
appointmentAlert: string;
|
appointmentAlert: string;
|
||||||
|
showPublicScores: boolean;
|
||||||
|
showPublicOpinions: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PublicOrganizationServiceViewParams = {
|
export type PublicOrganizationServiceViewParams = {
|
||||||
@@ -163,6 +165,8 @@ class Views {
|
|||||||
services,
|
services,
|
||||||
employees: services,
|
employees: services,
|
||||||
appointmentAlert: isNull<string>(company.appointmentAlert, ""),
|
appointmentAlert: isNull<string>(company.appointmentAlert, ""),
|
||||||
|
showPublicScores: company.showPublicScores ?? true,
|
||||||
|
showPublicOpinions: company.showPublicOpinions ?? true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ export interface MyOranizationsView {
|
|||||||
templateEmailCancellationId: string;
|
templateEmailCancellationId: string;
|
||||||
onboardingStep?: number;
|
onboardingStep?: number;
|
||||||
onboardingCompleted?: boolean;
|
onboardingCompleted?: boolean;
|
||||||
|
showPublicScores: boolean;
|
||||||
|
showPublicOpinions: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateCompanyParams = {
|
export type CreateCompanyParams = {
|
||||||
@@ -93,6 +95,8 @@ export type UpdateCompanyParams = {
|
|||||||
templateEmailCancellationId?: string;
|
templateEmailCancellationId?: string;
|
||||||
onboardingStep?: number;
|
onboardingStep?: number;
|
||||||
onboardingCompleted?: boolean;
|
onboardingCompleted?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DeleteCompanyParams = {
|
export type DeleteCompanyParams = {
|
||||||
@@ -158,6 +162,8 @@ export interface ICompany {
|
|||||||
onboardingCompleted?: boolean;
|
onboardingCompleted?: boolean;
|
||||||
fixedPostIds?: Array<string>;
|
fixedPostIds?: Array<string>;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PublicOrganizationViewParams = {
|
export type PublicOrganizationViewParams = {
|
||||||
@@ -184,6 +190,8 @@ export type PublicOrganizationView = {
|
|||||||
longitude: number;
|
longitude: number;
|
||||||
appointmentAlert: string;
|
appointmentAlert: string;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores: boolean;
|
||||||
|
showPublicOpinions: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SetNotificationAutoParams = {
|
export type SetNotificationAutoParams = {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ export type CreateServiceParams = {
|
|||||||
originalPrice: number;
|
originalPrice: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
sessionUser: string;
|
sessionUser: string;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateServiceParams = {
|
export type UpdateServiceParams = {
|
||||||
@@ -36,6 +38,8 @@ export type UpdateServiceParams = {
|
|||||||
fontColor?: string;
|
fontColor?: string;
|
||||||
fontShadowColor?: string;
|
fontShadowColor?: string;
|
||||||
sessionUser: string;
|
sessionUser: string;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PaginateServicesParams = {
|
export type PaginateServicesParams = {
|
||||||
@@ -110,6 +114,8 @@ export interface PublicServiceView {
|
|||||||
fontColor: string;
|
fontColor: string;
|
||||||
fontShadowColor: string;
|
fontShadowColor: string;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores: boolean;
|
||||||
|
showPublicOpinions: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PublicOrganizationServiceView {
|
export interface PublicOrganizationServiceView {
|
||||||
@@ -132,6 +138,8 @@ export interface IService {
|
|||||||
fontColor: string;
|
fontColor: string;
|
||||||
fontShadowColor: string;
|
fontShadowColor: string;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores?: boolean;
|
||||||
|
showPublicOpinions?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompanyServiceView {
|
export interface CompanyServiceView {
|
||||||
@@ -153,4 +161,6 @@ export interface CompanyServiceView {
|
|||||||
fontShadowColor: string;
|
fontShadowColor: string;
|
||||||
published: SERVICE_PUBLISHED_STATUS;
|
published: SERVICE_PUBLISHED_STATUS;
|
||||||
banned?: boolean;
|
banned?: boolean;
|
||||||
|
showPublicScores: boolean;
|
||||||
|
showPublicOpinions: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ import OrgConfigIcon from "@mui/icons-material/SettingsOutlined";
|
|||||||
import Textbox from "@components/Textbox/Textbox";
|
import Textbox from "@components/Textbox/Textbox";
|
||||||
import TextPhone from "@components/TextPhone/TextPhone";
|
import TextPhone from "@components/TextPhone/TextPhone";
|
||||||
import MaterialAlert from "@mui/material/Alert";
|
import MaterialAlert from "@mui/material/Alert";
|
||||||
|
import Checkbox from "@mui/material/Checkbox";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import {
|
import {
|
||||||
loadOrganizationsById,
|
loadOrganizationsById,
|
||||||
savePublishedStatus,
|
savePublishedStatus,
|
||||||
updateOrganizationsById,
|
updateOrganizationsById,
|
||||||
} from "../Org.Service";
|
} from "../Org.Service";
|
||||||
|
import { loadServicesByCompany, updateService } from "../services/Services.Service";
|
||||||
import {
|
import {
|
||||||
COMPANY_PUBLISHED_STATUS,
|
COMPANY_PUBLISHED_STATUS,
|
||||||
MyOranizationsView,
|
MyOranizationsView,
|
||||||
@@ -35,6 +37,7 @@ import { useConfirmStore } from "@core/Store/Confirm.Store";
|
|||||||
import Switch from "@core/app/components/Switch/Switch";
|
import Switch from "@core/app/components/Switch/Switch";
|
||||||
import { FindTemplatesParams } from "@core/Models/Templates.model";
|
import { FindTemplatesParams } from "@core/Models/Templates.model";
|
||||||
import filterObjects from "@core/app/components/TextObjectFilter/Filter.Service";
|
import filterObjects from "@core/app/components/TextObjectFilter/Filter.Service";
|
||||||
|
import { CompanyServiceView } from "@models/Service.model";
|
||||||
|
|
||||||
type UrlData = {
|
type UrlData = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -57,6 +60,13 @@ export default function OrganizationEdit() {
|
|||||||
const [cancellationTime, setCancellationTime] = useState("");
|
const [cancellationTime, setCancellationTime] = useState("");
|
||||||
const [appointmentAlert, setAppointmentAlert] = useState("");
|
const [appointmentAlert, setAppointmentAlert] = useState("");
|
||||||
const [orgSlug, setOrgSlug] = useState("");
|
const [orgSlug, setOrgSlug] = useState("");
|
||||||
|
const [showPublicScores, setShowPublicScores] = useState(true);
|
||||||
|
const [showPublicOpinions, setShowPublicOpinions] = useState(true);
|
||||||
|
const [servicesShowPublicScores, setServicesShowPublicScores] = useState(true);
|
||||||
|
const [servicesShowPublicOpinions, setServicesShowPublicOpinions] = useState(true);
|
||||||
|
const [originalServicesShowPublicScores, setOriginalServicesShowPublicScores] = useState(true);
|
||||||
|
const [originalServicesShowPublicOpinions, setOriginalServicesShowPublicOpinions] = useState(true);
|
||||||
|
const [services, setServices] = useState<CompanyServiceView[]>([]);
|
||||||
|
|
||||||
const [orgPublished, setOrgPublished] = useState<COMPANY_PUBLISHED_STATUS | undefined>(
|
const [orgPublished, setOrgPublished] = useState<COMPANY_PUBLISHED_STATUS | undefined>(
|
||||||
undefined
|
undefined
|
||||||
@@ -65,6 +75,8 @@ export default function OrganizationEdit() {
|
|||||||
const [savePublishedStatusAvailable, setSavePublishedStatusAvailable] = useState(false);
|
const [savePublishedStatusAvailable, setSavePublishedStatusAvailable] = useState(false);
|
||||||
|
|
||||||
const [combosLoaded, setCombosLoaded] = useState<boolean>(false);
|
const [combosLoaded, setCombosLoaded] = useState<boolean>(false);
|
||||||
|
const ownerSubscription = SessionInfo.organizationSubscriptions[id];
|
||||||
|
const canEditPublicRatingFlags = (ownerSubscription?.plan.price || 0) > 0;
|
||||||
|
|
||||||
const [categoryFilterContent] = useState<TextObjectModalContent>({
|
const [categoryFilterContent] = useState<TextObjectModalContent>({
|
||||||
header: (
|
header: (
|
||||||
@@ -210,28 +222,48 @@ export default function OrganizationEdit() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (combosLoaded) {
|
if (combosLoaded) {
|
||||||
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
eventHandler.setEventType(EVENT_TYPES.LOADING);
|
||||||
loadOrganizationsById({ id: id, sessionUser: SessionInfo.userId })
|
Promise.all([
|
||||||
.then((response: MyOranizationsView) => {
|
loadOrganizationsById({ id: id, sessionUser: SessionInfo.userId }),
|
||||||
setOrgName(response.name);
|
loadServicesByCompany(id),
|
||||||
setOrgDescription(response.description);
|
])
|
||||||
setHeatMapFraction(response.heatMapFraction.toString());
|
.then((response) => {
|
||||||
setAppointmentTime(response.appointmentTime.toString());
|
const [organization, loadedServices] = response;
|
||||||
setCancellationTime(response.cancellationTime.toString());
|
|
||||||
setAppointmentAlert(response.appointmentAlert);
|
setOrgName(organization.name);
|
||||||
setAreaCode(response.phoneAreaCode);
|
setOrgDescription(organization.description);
|
||||||
setPhone(response.phoneNumber);
|
setHeatMapFraction(organization.heatMapFraction.toString());
|
||||||
setCategoryId(response.categoryId.toString());
|
setAppointmentTime(organization.appointmentTime.toString());
|
||||||
setOrgSlug(getSlug(response.name));
|
setCancellationTime(organization.cancellationTime.toString());
|
||||||
setOrgPublished(response.published);
|
setAppointmentAlert(organization.appointmentAlert);
|
||||||
|
setAreaCode(organization.phoneAreaCode);
|
||||||
|
setPhone(organization.phoneNumber);
|
||||||
|
setCategoryId(organization.categoryId.toString());
|
||||||
|
setOrgSlug(getSlug(organization.name));
|
||||||
|
setOrgPublished(organization.published);
|
||||||
|
setShowPublicScores(organization.showPublicScores !== undefined ? organization.showPublicScores : true);
|
||||||
|
setShowPublicOpinions(organization.showPublicOpinions !== undefined ? organization.showPublicOpinions : true);
|
||||||
|
setServices(loadedServices);
|
||||||
|
setServicesShowPublicScores(
|
||||||
|
loadedServices.every((service) => service.showPublicScores !== false)
|
||||||
|
);
|
||||||
|
setServicesShowPublicOpinions(
|
||||||
|
loadedServices.every((service) => service.showPublicOpinions !== false)
|
||||||
|
);
|
||||||
|
setOriginalServicesShowPublicScores(
|
||||||
|
loadedServices.every((service) => service.showPublicScores !== false)
|
||||||
|
);
|
||||||
|
setOriginalServicesShowPublicOpinions(
|
||||||
|
loadedServices.every((service) => service.showPublicOpinions !== false)
|
||||||
|
);
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
setTemplateWapNotifId(response.templateWapNotifId);
|
setTemplateWapNotifId(organization.templateWapNotifId);
|
||||||
setTemplateWapAltaId(response.templateWapAltaId);
|
setTemplateWapAltaId(organization.templateWapAltaId);
|
||||||
setTemplateWapCancellationId(response.templateWapCancellationId);
|
setTemplateWapCancellationId(organization.templateWapCancellationId);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error: ApiError | Error) => {
|
||||||
alert.showError(error.format());
|
alert.showError(error instanceof ApiError ? error.format() : error.message);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
@@ -270,6 +302,12 @@ export default function OrganizationEdit() {
|
|||||||
templateWapNotifId: templateWapNotifId === "" ? undefined : templateWapNotifId,
|
templateWapNotifId: templateWapNotifId === "" ? undefined : templateWapNotifId,
|
||||||
templateWapAltaId: templateWapAltaId === "" ? undefined : templateWapAltaId,
|
templateWapAltaId: templateWapAltaId === "" ? undefined : templateWapAltaId,
|
||||||
templateWapCancellationId: templateWapCancellationId === "" ? undefined : templateWapCancellationId,
|
templateWapCancellationId: templateWapCancellationId === "" ? undefined : templateWapCancellationId,
|
||||||
|
...(canEditPublicRatingFlags
|
||||||
|
? {
|
||||||
|
showPublicScores,
|
||||||
|
showPublicOpinions,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const schema = Yup.object().shape({
|
const schema = Yup.object().shape({
|
||||||
@@ -335,10 +373,61 @@ export default function OrganizationEdit() {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
updateOrganizationsById(data)
|
updateOrganizationsById(data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
alert.showSuccess("Organizacion actualizada!");
|
const servicesShowPublicScoresChanged =
|
||||||
|
originalServicesShowPublicScores !== servicesShowPublicScores;
|
||||||
|
const servicesShowPublicOpinionsChanged =
|
||||||
|
originalServicesShowPublicOpinions !== servicesShowPublicOpinions;
|
||||||
|
const changedServices =
|
||||||
|
canEditPublicRatingFlags &&
|
||||||
|
(servicesShowPublicScoresChanged || servicesShowPublicOpinionsChanged)
|
||||||
|
? services
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
changedServices.map((service) =>
|
||||||
|
updateService({
|
||||||
|
id: service.id,
|
||||||
|
companyId: id,
|
||||||
|
name: service.name,
|
||||||
|
description: service.description,
|
||||||
|
originalPrice: service.originalPrice,
|
||||||
|
limit: service.limit,
|
||||||
|
length: service.length,
|
||||||
|
color: service.color,
|
||||||
|
fontColor: service.fontColor,
|
||||||
|
fontShadowColor: service.fontShadowColor,
|
||||||
|
sessionUser: SessionInfo.userId,
|
||||||
|
showPublicScores: servicesShowPublicScoresChanged
|
||||||
|
? servicesShowPublicScores
|
||||||
|
: service.showPublicScores !== undefined
|
||||||
|
? service.showPublicScores
|
||||||
|
: true,
|
||||||
|
showPublicOpinions: servicesShowPublicOpinionsChanged
|
||||||
|
? servicesShowPublicOpinions
|
||||||
|
: service.showPublicOpinions !== undefined
|
||||||
|
? service.showPublicOpinions
|
||||||
|
: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).then(() => {
|
||||||
|
const updatedServices = services.map((service) => ({
|
||||||
|
...service,
|
||||||
|
showPublicScores: servicesShowPublicScoresChanged
|
||||||
|
? servicesShowPublicScores
|
||||||
|
: service.showPublicScores,
|
||||||
|
showPublicOpinions: servicesShowPublicOpinionsChanged
|
||||||
|
? servicesShowPublicOpinions
|
||||||
|
: service.showPublicOpinions,
|
||||||
|
}));
|
||||||
|
|
||||||
|
setServices(updatedServices);
|
||||||
|
setOriginalServicesShowPublicScores(servicesShowPublicScores);
|
||||||
|
setOriginalServicesShowPublicOpinions(servicesShowPublicOpinions);
|
||||||
|
alert.showSuccess("Organizacion actualizada!");
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch((error: ApiError) => {
|
.catch((error: ApiError | Error) => {
|
||||||
alert.showError(error.format());
|
alert.showError(error instanceof ApiError ? error.format() : error.message);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
@@ -484,6 +573,83 @@ export default function OrganizationEdit() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
||||||
|
<b>Visibilidad pública:</b> Elegí si querés mostrar puntuaciones y opiniones en el perfil público y las páginas de reserva. Disponible para planes pagos.
|
||||||
|
</MaterialAlert>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "10px", marginTop: "10px" }}>
|
||||||
|
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
||||||
|
<Checkbox
|
||||||
|
checked={showPublicScores}
|
||||||
|
disabled={!canEditPublicRatingFlags}
|
||||||
|
onChange={(event) => {
|
||||||
|
setShowPublicScores(event.target.checked);
|
||||||
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Mostrar puntuaciones públicas
|
||||||
|
</label>
|
||||||
|
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
||||||
|
<Checkbox
|
||||||
|
checked={showPublicOpinions}
|
||||||
|
disabled={!canEditPublicRatingFlags}
|
||||||
|
onChange={(event) => {
|
||||||
|
setShowPublicOpinions(event.target.checked);
|
||||||
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Mostrar opiniones públicas
|
||||||
|
</label>
|
||||||
|
{!canEditPublicRatingFlags && (
|
||||||
|
<span style={{ color: "var(--gray-darkest)", fontSize: "13px" }}>
|
||||||
|
Disponible para planes pagos.
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{services.length > 0 && (
|
||||||
|
<>
|
||||||
|
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
||||||
|
<b>Visibilidad pública de servicios:</b> Configurá si se muestran puntuaciones y opiniones en todos los servicios. Disponible para planes pagos.
|
||||||
|
</MaterialAlert>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "10px",
|
||||||
|
marginTop: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
||||||
|
<Checkbox
|
||||||
|
checked={servicesShowPublicScores}
|
||||||
|
disabled={!canEditPublicRatingFlags}
|
||||||
|
onChange={(event) => {
|
||||||
|
setServicesShowPublicScores(event.target.checked);
|
||||||
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Mostrar puntuaciones públicas de los servicios
|
||||||
|
</label>
|
||||||
|
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
||||||
|
<Checkbox
|
||||||
|
checked={servicesShowPublicOpinions}
|
||||||
|
disabled={!canEditPublicRatingFlags}
|
||||||
|
onChange={(event) => {
|
||||||
|
setServicesShowPublicOpinions(event.target.checked);
|
||||||
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Mostrar opiniones públicas de los servicios
|
||||||
|
</label>
|
||||||
|
{!canEditPublicRatingFlags && (
|
||||||
|
<span style={{ color: "var(--gray-darkest)", fontSize: "13px" }}>
|
||||||
|
Para cambiar la visibilidad pública de los servicios necesitás un plan pago.
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<TextObjectFilter
|
<TextObjectFilter
|
||||||
placeholder="Categoría"
|
placeholder="Categoría"
|
||||||
content={categoryFilterContent}
|
content={categoryFilterContent}
|
||||||
|
|||||||
+51
@@ -72,6 +72,8 @@ export default function OrganizationService() {
|
|||||||
const [serviceColor, setServiceColor] = useState("");
|
const [serviceColor, setServiceColor] = useState("");
|
||||||
const [serviceFontColor, setServiceFontColor] = useState("");
|
const [serviceFontColor, setServiceFontColor] = useState("");
|
||||||
const [serviceFontShadowColor, setServiceFontShadowColor] = useState("");
|
const [serviceFontShadowColor, setServiceFontShadowColor] = useState("");
|
||||||
|
const [showPublicScores, setShowPublicScores] = useState(true);
|
||||||
|
const [showPublicOpinions, setShowPublicOpinions] = useState(true);
|
||||||
|
|
||||||
const [serviceDiscountType, setServiceDiscountType] = useState<string | undefined>(undefined);
|
const [serviceDiscountType, setServiceDiscountType] = useState<string | undefined>(undefined);
|
||||||
const [serviceDiscountValue, setServiceDiscountValue] = useState<number | undefined>(undefined);
|
const [serviceDiscountValue, setServiceDiscountValue] = useState<number | undefined>(undefined);
|
||||||
@@ -116,6 +118,8 @@ export default function OrganizationService() {
|
|||||||
|
|
||||||
const [discountsFilterData, setDiscountsFilterData] = useState<TextObjectFilterResult[]>([]);
|
const [discountsFilterData, setDiscountsFilterData] = useState<TextObjectFilterResult[]>([]);
|
||||||
const [discountId, setDiscountId] = useState<string>("");
|
const [discountId, setDiscountId] = useState<string>("");
|
||||||
|
const ownerSubscription = SessionInfo.organizationSubscriptions[id];
|
||||||
|
const canEditPublicRatingFlags = (ownerSubscription?.plan.price || 0) > 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
eventHandler.setEventType(EVENT_TYPES.SLEEP);
|
||||||
@@ -200,6 +204,12 @@ export default function OrganizationService() {
|
|||||||
limit: parseInt(serviceLimit),
|
limit: parseInt(serviceLimit),
|
||||||
length: parseInt(serviceLength),
|
length: parseInt(serviceLength),
|
||||||
sessionUser: SessionInfo.userId,
|
sessionUser: SessionInfo.userId,
|
||||||
|
...(canEditPublicRatingFlags
|
||||||
|
? {
|
||||||
|
showPublicScores,
|
||||||
|
showPublicOpinions,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
alert.showSuccess("Servicio creado");
|
alert.showSuccess("Servicio creado");
|
||||||
@@ -225,6 +235,12 @@ export default function OrganizationService() {
|
|||||||
fontColor: serviceFontColor,
|
fontColor: serviceFontColor,
|
||||||
fontShadowColor: serviceFontShadowColor,
|
fontShadowColor: serviceFontShadowColor,
|
||||||
sessionUser: SessionInfo.userId,
|
sessionUser: SessionInfo.userId,
|
||||||
|
...(canEditPublicRatingFlags
|
||||||
|
? {
|
||||||
|
showPublicScores,
|
||||||
|
showPublicOpinions,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
alert.showSuccess("Servicio Actualizado");
|
alert.showSuccess("Servicio Actualizado");
|
||||||
@@ -255,6 +271,8 @@ export default function OrganizationService() {
|
|||||||
setServiceDiscountType(response.discountType);
|
setServiceDiscountType(response.discountType);
|
||||||
setServiceDiscountValue(response.discountValue);
|
setServiceDiscountValue(response.discountValue);
|
||||||
setServiceDiscountName(response.discountName);
|
setServiceDiscountName(response.discountName);
|
||||||
|
setShowPublicScores(response.showPublicScores !== undefined ? response.showPublicScores : true);
|
||||||
|
setShowPublicOpinions(response.showPublicOpinions !== undefined ? response.showPublicOpinions : true);
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -486,6 +504,39 @@ export default function OrganizationService() {
|
|||||||
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<MaterialAlert severity="info" sx={{ marginTop: "20px" }}>
|
||||||
|
<b>Visibilidad pública:</b> Elegí si querés mostrar puntuaciones y opiniones de este servicio en páginas públicas. Disponible para planes pagos.
|
||||||
|
</MaterialAlert>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "10px", marginTop: "10px" }}>
|
||||||
|
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
||||||
|
<Switch
|
||||||
|
checked={showPublicScores}
|
||||||
|
disabled={!canEditPublicRatingFlags}
|
||||||
|
onChange={(checked) => {
|
||||||
|
setShowPublicScores(checked);
|
||||||
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Mostrar puntuaciones públicas
|
||||||
|
</label>
|
||||||
|
<label style={{ display: "flex", alignItems: "center", gap: "10px", fontWeight: 600 }}>
|
||||||
|
<Switch
|
||||||
|
checked={showPublicOpinions}
|
||||||
|
disabled={!canEditPublicRatingFlags}
|
||||||
|
onChange={(checked) => {
|
||||||
|
setShowPublicOpinions(checked);
|
||||||
|
eventHandler.setEventType(EVENT_TYPES.NEED_SAVE);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Mostrar opiniones públicas
|
||||||
|
</label>
|
||||||
|
{!canEditPublicRatingFlags && (
|
||||||
|
<span style={{ color: "var(--gray-darkest)", fontSize: "13px" }}>
|
||||||
|
Disponible para planes pagos.
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<Textbox
|
<Textbox
|
||||||
name="servicePrice"
|
name="servicePrice"
|
||||||
placeholder="Precio del servicio"
|
placeholder="Precio del servicio"
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ export default function OrganizationHeader(props: OrganizationHeaderProps) {
|
|||||||
const [ratingSummary, setRatingSummary] = useState<RatingTargetSummaryResult>({ averageScore: 0, totalCount: 0 });
|
const [ratingSummary, setRatingSummary] = useState<RatingTargetSummaryResult>({ averageScore: 0, totalCount: 0 });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (organization.showPublicScores === false) {
|
||||||
|
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!organization.id) {
|
if (!organization.id) {
|
||||||
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
||||||
return;
|
return;
|
||||||
@@ -32,7 +37,7 @@ export default function OrganizationHeader(props: OrganizationHeaderProps) {
|
|||||||
.catch(() => {
|
.catch(() => {
|
||||||
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
||||||
});
|
});
|
||||||
}, [organization.id]);
|
}, [organization.id, organization.showPublicScores]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -67,7 +72,7 @@ export default function OrganizationHeader(props: OrganizationHeaderProps) {
|
|||||||
>
|
>
|
||||||
{organization.description}
|
{organization.description}
|
||||||
</p>
|
</p>
|
||||||
{ratingSummary.totalCount > 0 && (
|
{organization.showPublicScores !== false && ratingSummary.totalCount > 0 && (
|
||||||
<div className={style.organizationRatingSummary}>
|
<div className={style.organizationRatingSummary}>
|
||||||
<Rating
|
<Rating
|
||||||
className={style.organizationRatingStars}
|
className={style.organizationRatingStars}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export default function ProductItem(props: ProductItemProps) {
|
|||||||
variant="card"
|
variant="card"
|
||||||
displayMode="compact"
|
displayMode="compact"
|
||||||
showOpinionCount={false}
|
showOpinionCount={false}
|
||||||
|
enabled={product.showPublicScores !== false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={style.cardHeader}>
|
<div className={style.cardHeader}>
|
||||||
@@ -126,7 +127,12 @@ export default function ProductItem(props: ProductItemProps) {
|
|||||||
<div className={style.itemContent}>
|
<div className={style.itemContent}>
|
||||||
<div className={style.itemHeader}>
|
<div className={style.itemHeader}>
|
||||||
<h3 className={style.itemTitle}>{product.name}</h3>
|
<h3 className={style.itemTitle}>{product.name}</h3>
|
||||||
<ServiceRatingSummary serviceId={product.id} variant="row" showOpinionCount={false} />
|
<ServiceRatingSummary
|
||||||
|
serviceId={product.id}
|
||||||
|
variant="row"
|
||||||
|
showOpinionCount={false}
|
||||||
|
enabled={product.showPublicScores !== false}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
|
|||||||
@@ -32,6 +32,16 @@ const renderStars = (score: number): string => {
|
|||||||
|
|
||||||
const formatScore = (score: number): string => score.toFixed(1);
|
const formatScore = (score: number): string => score.toFixed(1);
|
||||||
|
|
||||||
|
const sortReviewsByScore = (reviews: RatingTargetReviewItem[]): RatingTargetReviewItem[] => {
|
||||||
|
return [...reviews].sort((firstReview, secondReview) => {
|
||||||
|
if (secondReview.score !== firstReview.score) {
|
||||||
|
return secondReview.score - firstReview.score;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Date(secondReview.createdAt).getTime() - new Date(firstReview.createdAt).getTime();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export default function ReviewsCarousel({
|
export default function ReviewsCarousel({
|
||||||
targetType,
|
targetType,
|
||||||
targetId,
|
targetId,
|
||||||
@@ -50,7 +60,7 @@ export default function ReviewsCarousel({
|
|||||||
ratingTargetReviews({ targetType, targetId, limit })
|
ratingTargetReviews({ targetType, targetId, limit })
|
||||||
.then((targetReviews) => {
|
.then((targetReviews) => {
|
||||||
if (active) {
|
if (active) {
|
||||||
setReviews(targetReviews.filter((review) => review.comment.trim().length > 0));
|
setReviews(sortReviewsByScore(targetReviews.filter((review) => review.comment.trim().length > 0)));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -10,13 +10,19 @@ export interface ServiceRatingSummaryProps {
|
|||||||
variant?: "card" | "row";
|
variant?: "card" | "row";
|
||||||
displayMode?: "default" | "compact";
|
displayMode?: "default" | "compact";
|
||||||
showOpinionCount?: boolean;
|
showOpinionCount?: boolean;
|
||||||
|
enabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ServiceRatingSummary(props: ServiceRatingSummaryProps): React.ReactElement | null {
|
export default function ServiceRatingSummary(props: ServiceRatingSummaryProps): React.ReactElement | null {
|
||||||
const { serviceId, variant = "card", displayMode = "default", showOpinionCount = true } = props;
|
const { serviceId, variant = "card", displayMode = "default", showOpinionCount = true, enabled = true } = props;
|
||||||
const [ratingSummary, setRatingSummary] = useState<RatingTargetSummaryResult>({ averageScore: 0, totalCount: 0 });
|
const [ratingSummary, setRatingSummary] = useState<RatingTargetSummaryResult>({ averageScore: 0, totalCount: 0 });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!enabled) {
|
||||||
|
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!serviceId) {
|
if (!serviceId) {
|
||||||
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
setRatingSummary({ averageScore: 0, totalCount: 0 });
|
||||||
return;
|
return;
|
||||||
@@ -42,9 +48,9 @@ export default function ServiceRatingSummary(props: ServiceRatingSummaryProps):
|
|||||||
return () => {
|
return () => {
|
||||||
isMounted = false;
|
isMounted = false;
|
||||||
};
|
};
|
||||||
}, [serviceId]);
|
}, [serviceId, enabled]);
|
||||||
|
|
||||||
if (ratingSummary.totalCount <= 0) {
|
if (!enabled || ratingSummary.totalCount <= 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,15 @@ import MuiSwitch from "@mui/material/Switch";
|
|||||||
interface SwitchProps {
|
interface SwitchProps {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
onChange: (checked: boolean) => void;
|
onChange: (checked: boolean) => void;
|
||||||
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Switch({ checked, onChange }: SwitchProps) {
|
export default function Switch({ checked, onChange, disabled = false }: SwitchProps) {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={turnosXpressTheme}>
|
<ThemeProvider theme={turnosXpressTheme}>
|
||||||
<MuiSwitch
|
<MuiSwitch
|
||||||
checked={checked}
|
checked={checked}
|
||||||
|
disabled={disabled}
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
onChange(event.target.checked);
|
onChange(event.target.checked);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -874,13 +874,15 @@ export default function OrganizationPublicProfile() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ReviewsCarousel
|
{orgData.showPublicOpinions !== false && (
|
||||||
targetType={RatingTargetType.COMPANY}
|
<ReviewsCarousel
|
||||||
targetId={orgData.id}
|
targetType={RatingTargetType.COMPANY}
|
||||||
title="Lo que dicen quienes ya visitaron esta organización"
|
targetId={orgData.id}
|
||||||
subtitle="Opiniones reales de personas que reservaron turnos acá."
|
title="Lo que dicen quienes ya visitaron esta organización"
|
||||||
className={style.organizationReviews}
|
subtitle="Opiniones reales de personas que reservaron turnos acá."
|
||||||
/>
|
className={style.organizationReviews}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -82,12 +82,14 @@ export default async function OrganizationPublicProfile({ params }: Props) {
|
|||||||
title="Otros Servicios 🏆"
|
title="Otros Servicios 🏆"
|
||||||
data={organizationService.organization.services.data}
|
data={organizationService.organization.services.data}
|
||||||
/>
|
/>
|
||||||
<ReviewsCarousel
|
{organizationService.service.showPublicOpinions !== false && (
|
||||||
targetType={RatingTargetType.SERVICE}
|
<ReviewsCarousel
|
||||||
targetId={sid}
|
targetType={RatingTargetType.SERVICE}
|
||||||
title="Lo que dicen quienes ya reservaron"
|
targetId={sid}
|
||||||
subtitle="Comentarios de clientes que calificaron este servicio después de su turno."
|
title="Lo que dicen quienes ya reservaron"
|
||||||
/>
|
subtitle="Comentarios de clientes que calificaron este servicio después de su turno."
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</AnimatedContainer>
|
</AnimatedContainer>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user