.
This commit is contained in:
parent
8ad1c63acc
commit
533b22dd98
@ -10,7 +10,7 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
import { Layout, LayoutContent, LayoutHeader } from "@/components";
|
import { Layout, LayoutContent, LayoutHeader } from "@/components";
|
||||||
import { useGetIdentity } from "@/lib/hooks";
|
import { useGetProfile } from "@/lib/hooks";
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
@ -49,7 +49,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
|
|
||||||
export const DashboardPage = () => {
|
export const DashboardPage = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { data: userIdentity, status } = useGetIdentity();
|
const { data: userIdentity, status } = useGetProfile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
|
|||||||
@ -202,14 +202,8 @@ export const QuoteEdit = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormCurrencyField
|
<QuoteGeneralCardEditor />
|
||||||
currency={quoteCurrency}
|
<QuoteDetailsCardEditor currency={quoteCurrency} />
|
||||||
precision={4}
|
|
||||||
className='text-right'
|
|
||||||
label={"subtotal_price"}
|
|
||||||
disabled={form.formState.disabled}
|
|
||||||
{...form.register("subtotal_price")}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Tabs defaultValue='items' className='space-y-4'>
|
<Tabs defaultValue='items' className='space-y-4'>
|
||||||
<TabsList>
|
<TabsList>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useCustomDialog, useGetIdentity } from "@/lib/hooks";
|
import { useCustomDialog, useGetProfile } from "@/lib/hooks";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@ -32,7 +32,7 @@ export const UserButton = () => {
|
|||||||
navigate("/logout");
|
navigate("/logout");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { data, status } = useGetIdentity();
|
const { data, status } = useGetProfile();
|
||||||
|
|
||||||
const openUserMenu = (event: SyntheticEvent) => {
|
const openUserMenu = (event: SyntheticEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export const createAxiosAuthActions = (
|
|||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
data,
|
data,
|
||||||
redirectTo: "/",
|
redirectTo: "/home",
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
@ -61,10 +61,18 @@ export const createAxiosAuthActions = (
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
getIdentity: async () => {
|
getProfile: async () => {
|
||||||
|
/**
|
||||||
|
* id: string;
|
||||||
|
* name: string;
|
||||||
|
* email: string;
|
||||||
|
* lang_code: string;
|
||||||
|
* roles: string[];
|
||||||
|
*/
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await httpClient.request<IIdentity_Response_DTO>({
|
const result = await httpClient.request<IIdentity_Response_DTO>({
|
||||||
url: `${apiUrl}/auth/identity`,
|
url: `${apiUrl}/profile`,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { IIdentity_Response_DTO } from "@shared/contexts";
|
import { IGetProfileResponse_DTO } from "@shared/contexts";
|
||||||
|
|
||||||
export type SuccessNotificationResponse = {
|
export type SuccessNotificationResponse = {
|
||||||
message: string;
|
message: string;
|
||||||
@ -7,7 +7,7 @@ export type SuccessNotificationResponse = {
|
|||||||
|
|
||||||
export type PermissionResponse = unknown;
|
export type PermissionResponse = unknown;
|
||||||
|
|
||||||
export type IdentityResponse = IIdentity_Response_DTO | null;
|
export type ProfileResponse = IGetProfileResponse_DTO | null;
|
||||||
|
|
||||||
export type AuthActionCheckResponse = {
|
export type AuthActionCheckResponse = {
|
||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
@ -39,5 +39,5 @@ export interface IAuthActions {
|
|||||||
forgotPassword?: (params: unknown) => Promise<AuthActionResponse>;
|
forgotPassword?: (params: unknown) => Promise<AuthActionResponse>;
|
||||||
updatePassword?: (params: unknown) => Promise<AuthActionResponse>;
|
updatePassword?: (params: unknown) => Promise<AuthActionResponse>;
|
||||||
getPermissions?: (params?: Record<string, unknown>) => Promise<PermissionResponse>;
|
getPermissions?: (params?: Record<string, unknown>) => Promise<PermissionResponse>;
|
||||||
getIdentity?: (params?: unknown) => Promise<IdentityResponse>;
|
getProfile?: (params?: unknown) => Promise<ProfileResponse>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export * from "./AuthActions";
|
export * from "./AuthActions";
|
||||||
export * from "./AuthContext";
|
export * from "./AuthContext";
|
||||||
export * from "./useAuth";
|
export * from "./useAuth";
|
||||||
export * from "./useGetIdentity";
|
export * from "./useGetProfile";
|
||||||
export * from "./useIsLoggedIn";
|
export * from "./useIsLoggedIn";
|
||||||
export * from "./useLogin";
|
export * from "./useLogin";
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
import { IdentityResponse, useAuth } from "@/lib/hooks";
|
|
||||||
import { UseQueryOptions, useQuery } from "@tanstack/react-query";
|
|
||||||
import { useQueryKey } from "../useQueryKey";
|
|
||||||
|
|
||||||
export const useGetIdentity = (queryOptions?: UseQueryOptions<IdentityResponse>) => {
|
|
||||||
const keys = useQueryKey();
|
|
||||||
const { getIdentity } = useAuth();
|
|
||||||
|
|
||||||
const result = useQuery<IdentityResponse>({
|
|
||||||
queryKey: keys().auth().action("identity").get(),
|
|
||||||
queryFn: getIdentity,
|
|
||||||
...queryOptions,
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
16
client/src/lib/hooks/useAuth/useGetProfile.ts
Normal file
16
client/src/lib/hooks/useAuth/useGetProfile.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ProfileResponse, useAuth } from "@/lib/hooks";
|
||||||
|
import { UseQueryOptions, useQuery } from "@tanstack/react-query";
|
||||||
|
import { useQueryKey } from "../useQueryKey";
|
||||||
|
|
||||||
|
export const useGetProfile = (queryOptions?: UseQueryOptions<ProfileResponse>) => {
|
||||||
|
const keys = useQueryKey();
|
||||||
|
const { getProfile } = useAuth();
|
||||||
|
|
||||||
|
const result = useQuery<ProfileResponse>({
|
||||||
|
queryKey: keys().auth().action("profile").get(),
|
||||||
|
queryFn: getProfile,
|
||||||
|
...queryOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
@ -17,7 +17,7 @@ export const useLogin = (params?: UseMutationOptions<AuthActionResponse, Error,
|
|||||||
onSuccess: (data, variables, context) => {
|
onSuccess: (data, variables, context) => {
|
||||||
const { success, redirectTo } = data;
|
const { success, redirectTo } = data;
|
||||||
if (success && redirectTo) {
|
if (success && redirectTo) {
|
||||||
navigate(redirectTo || "/", { replace: true });
|
navigate(redirectTo || "/home", { replace: false });
|
||||||
}
|
}
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess(data, variables, context);
|
onSuccess(data, variables, context);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useGetIdentity } from "../useAuth";
|
import { useGetProfile } from "../useAuth";
|
||||||
|
|
||||||
export const usePreferredLanguage = () => {
|
export const usePreferredLanguage = () => {
|
||||||
const { data } = useGetIdentity();
|
const { data } = useGetProfile();
|
||||||
|
|
||||||
if (!data || !data.language) {
|
if (!data || !data.language) {
|
||||||
return navigator.languages && navigator.languages.length
|
return navigator.languages && navigator.languages.length
|
||||||
|
|||||||
@ -16,7 +16,7 @@ type DataMutationActions =
|
|||||||
type AuthActionType =
|
type AuthActionType =
|
||||||
| "login"
|
| "login"
|
||||||
| "logout"
|
| "logout"
|
||||||
| "identity"
|
| "profile"
|
||||||
| "register"
|
| "register"
|
||||||
| "forgotPassword"
|
| "forgotPassword"
|
||||||
| "check"
|
| "check"
|
||||||
|
|||||||
@ -4,36 +4,243 @@
|
|||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"Accept": "Accept"
|
"save": "Save",
|
||||||
|
"accept": "OK",
|
||||||
|
"hide": "Ocultar",
|
||||||
|
"back": "Back",
|
||||||
|
"upload": "Upload",
|
||||||
|
"continue": "Continue",
|
||||||
|
"sort_asc": "Asc",
|
||||||
|
"sort_asc_description": "En order ascendente. Click para ordenar descendentemente.",
|
||||||
|
"sort_desc": "Desc",
|
||||||
|
"sort_desc_description": "En orden descendente. Click para ordenar ascendentemente.",
|
||||||
|
"sort_none_description": "Sin orden. Click para ordenar ascendentemente.",
|
||||||
|
"rows_selected": "{{count}} de {{total}} fila(s) seleccionadas.",
|
||||||
|
"rows_per_page": "Filas por página",
|
||||||
|
"num_page_of_total": "Página {{count}} de {{total}}",
|
||||||
|
"go_to_first_page": "Ir a la primera página",
|
||||||
|
"go_to_prev_page": "Ir a la página anterior",
|
||||||
|
"go_to_next_page": "Ir a la página siguiente",
|
||||||
|
"go_to_last_page": "Ir a la última página",
|
||||||
|
"filter_placeholder": "Escribe aquí para filtrar...",
|
||||||
|
"reset_filter": "Quitar el filtro",
|
||||||
|
"error": "Error",
|
||||||
|
"actions": "Acciones",
|
||||||
|
"open_menu": "Abrir el menú",
|
||||||
|
"duplicate_rows": "Duplicar",
|
||||||
|
"duplicate_rows_tooltip": "Duplica las fila(s) seleccionadas(s)",
|
||||||
|
"pick_date": "Elige una fecha",
|
||||||
|
"required_field": "Este campo es obligatorio",
|
||||||
|
"unsaved_changes_prompt": "Los últimos cambios no se han guardado. Si continúas, se perderán",
|
||||||
|
"edit": "Editar"
|
||||||
},
|
},
|
||||||
"main_menu": {
|
"main_menu": {
|
||||||
"home": "Home",
|
"home": "Inicio",
|
||||||
"settings": "Settings",
|
"settings": "Ajustes",
|
||||||
"dealers": "Dealers",
|
"dealers": "Distribuidores",
|
||||||
"catalog": "Catalog",
|
"catalog": "Catálogo",
|
||||||
"quotes": "Quotes",
|
"quotes": "Cotizaciones",
|
||||||
"search_placeholder": "Search product, quotes, etc...",
|
"search_placeholder": "Buscar productos, cotizaciones, etc...",
|
||||||
"user": {
|
"user": {
|
||||||
"user_menu": "User menu",
|
"user_menu": "Menú del usuario",
|
||||||
"my_account": "My account",
|
"my_account": "Mi cuenta",
|
||||||
"profile": "Profile",
|
"profile": "Perfil",
|
||||||
"settings": "Settings",
|
"settings": "Ajustes",
|
||||||
"support": "Support",
|
"support": "Soporte",
|
||||||
"logout": "Logout"
|
"logout": "Salir"
|
||||||
},
|
},
|
||||||
"logout": {}
|
"logout": {}
|
||||||
},
|
},
|
||||||
"login_page": {
|
"login_page": {
|
||||||
"title": "Uecko Quotes",
|
"title": "Presupuestador para distribuidores",
|
||||||
"description": "Enter your email address and password to login",
|
"description": "Introduzca su dirección de correo electrónico y contraseña para acceder",
|
||||||
"email_label": "Email",
|
"email_label": "Email",
|
||||||
"email_placeholder": "user@sample.com",
|
"email_placeholder": "micorreo@ejemplo.com",
|
||||||
"password_label": "Password",
|
"password_label": "Contraseña",
|
||||||
"forgotten_password": "Forgot your password?",
|
"forgotten_password": "¿Has olvidado tu contraseña?",
|
||||||
"become_dealer": "Do you want to become a Uecko dealer?",
|
"become_dealer": "¿Quieres ser distribuidor de Uecko?",
|
||||||
"contact_us": "Contact us",
|
"contact_us": "Contacta con nosotros",
|
||||||
"login": "Login",
|
"login": "Entrar"
|
||||||
"error": "Error"
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"welcome": "Bienvenido"
|
||||||
|
},
|
||||||
|
"catalog": {
|
||||||
|
"list": {
|
||||||
|
"title": "Catálogo de artículos",
|
||||||
|
"columns": {
|
||||||
|
"description": "Descripción",
|
||||||
|
"points": "Puntos",
|
||||||
|
"retail_price": "PVP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"quotes": {
|
||||||
|
"list": {
|
||||||
|
"title": "Quotes",
|
||||||
|
"subtitle": "",
|
||||||
|
"tabs": {
|
||||||
|
"all": "All",
|
||||||
|
"draft": "Draft",
|
||||||
|
"archived": "Archive"
|
||||||
|
},
|
||||||
|
"columns": {
|
||||||
|
"date": "Date",
|
||||||
|
"reference": "Reference",
|
||||||
|
"status": "Status",
|
||||||
|
"customer_information": "Customer",
|
||||||
|
"total_price": "Imp. total"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"create": {
|
||||||
|
"title": "New quote",
|
||||||
|
"buttons": {
|
||||||
|
"save_quote": "Guardar cotización",
|
||||||
|
"discard": "Descartar"
|
||||||
|
},
|
||||||
|
"tabs": {
|
||||||
|
"general": "Datos generales",
|
||||||
|
"items": "Contenido",
|
||||||
|
"documents": "Documentos",
|
||||||
|
"history": "Historial"
|
||||||
|
},
|
||||||
|
"form_groups": {
|
||||||
|
"general": {
|
||||||
|
"title": "Datos generales",
|
||||||
|
"desc": "Datos generales y cliente al que va la cotización"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"title": "Estado",
|
||||||
|
"desc": "Estado de la cotización"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"title": "Contenido de la cotización",
|
||||||
|
"desc": "Líneas de detalle de la cotización. Ayúdese del catálogo para rellenar más fácilmente el contenido."
|
||||||
|
},
|
||||||
|
"documents": {
|
||||||
|
"title": "Documentos",
|
||||||
|
"desc": "Añada adjuntar con su cotización documentos como fotos, planos, croquis, etc."
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"title": "",
|
||||||
|
"desc": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"title": "Cotización"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"title": "Cotización"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"draft": "Borrador"
|
||||||
|
},
|
||||||
|
"form_fields": {
|
||||||
|
"date": {
|
||||||
|
"label": "Fecha",
|
||||||
|
"desc": "Fecha de esta cotización",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"reference": {
|
||||||
|
"label": "Referencia",
|
||||||
|
"desc": "Referencia para esta cotización",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"lang_code": {
|
||||||
|
"label": "Idioma",
|
||||||
|
"desc": "Idioma de la cotización",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"currency_code": {
|
||||||
|
"label": "Moneda",
|
||||||
|
"desc": "Moneda de la cotización",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"customer_information": {
|
||||||
|
"label": "Datos del cliente",
|
||||||
|
"desc": "Escriba el nombre del cliente en la primera línea, la direccion en la segunda y el código postal y ciudad en la tercera.",
|
||||||
|
"placeholder": "Nombre y apellidos\nCalle y número\nCódigo postal y ciudad..."
|
||||||
|
},
|
||||||
|
"payment_method": {
|
||||||
|
"label": "Forma de pago",
|
||||||
|
"placeholder": "placeholder",
|
||||||
|
"desc": "desc"
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"label": "Notas",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": "desc"
|
||||||
|
},
|
||||||
|
"validity": {
|
||||||
|
"label": "Validez de la cotización",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": "desc"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"quantity": {
|
||||||
|
"label": "Cantidad",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": ""
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"label": "Descripción",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": ""
|
||||||
|
},
|
||||||
|
"unit_price": {
|
||||||
|
"label": "Imp. unitario",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": "Importe unitario del artículo"
|
||||||
|
},
|
||||||
|
"subtotal_price": {
|
||||||
|
"label": "Subtotal",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": ""
|
||||||
|
},
|
||||||
|
"discount": {
|
||||||
|
"label": "Dto (%)",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": "Porcentaje de descuento"
|
||||||
|
},
|
||||||
|
"total_price": {
|
||||||
|
"label": "Imp. total",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": "Importe total con el descuento ya aplicado"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Ajustes",
|
||||||
|
"quotes": {
|
||||||
|
"title": "Cotizaciones",
|
||||||
|
"contact_information": {
|
||||||
|
"label": "Información de contacto",
|
||||||
|
"placeholder": "placeholder",
|
||||||
|
"desc": "Información de contacto"
|
||||||
|
},
|
||||||
|
"default_payment_method": {
|
||||||
|
"label": "Forma de pago",
|
||||||
|
"placeholder": "placeholder",
|
||||||
|
"desc": "desc"
|
||||||
|
},
|
||||||
|
"default_notes": {
|
||||||
|
"label": "Notas",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": "desc"
|
||||||
|
},
|
||||||
|
"default_legal_terms": {
|
||||||
|
"label": "Cláusulas legales",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": "desc"
|
||||||
|
},
|
||||||
|
"default_quote_validity": {
|
||||||
|
"label": "Validez por defecto",
|
||||||
|
"placeholder": "",
|
||||||
|
"desc": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export interface IAuthUser {
|
|||||||
isUser: boolean;
|
isUser: boolean;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
getRoles: () => AuthUserRole[];
|
getRoles: () => AuthUserRole[];
|
||||||
|
getRolesArray: () => string[];
|
||||||
|
|
||||||
verifyPassword: (candidatePassword: string) => boolean;
|
verifyPassword: (candidatePassword: string) => boolean;
|
||||||
}
|
}
|
||||||
@ -77,6 +78,10 @@ export class AuthUser extends AggregateRoot<IAuthUserProps> implements IAuthUser
|
|||||||
return this.roles;
|
return this.roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getRolesArray(): string[] {
|
||||||
|
return this.getRoles()?.map((rol) => rol.toString());
|
||||||
|
}
|
||||||
|
|
||||||
public verifyPassword(candidatePassword: string): boolean {
|
public verifyPassword(candidatePassword: string): boolean {
|
||||||
return this.props.password.verifyPassword(candidatePassword);
|
return this.props.password.verifyPassword(candidatePassword);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,8 @@ export const identityPresenter: IIdentityPresenter = {
|
|||||||
id: user.id.toString(),
|
id: user.id.toString(),
|
||||||
name: user.name.toString(),
|
name: user.name.toString(),
|
||||||
email: user.email.toString(),
|
email: user.email.toString(),
|
||||||
language: user.language.toString(),
|
lang_code: user.language.toString(),
|
||||||
roles: user.getRoles()?.map((rol) => rol.toString()),
|
roles: user.getRolesArray(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,20 +1,40 @@
|
|||||||
import { AggregateRoot, IDomainError, Result, UniqueID } from "@shared/contexts";
|
import { DealerStatus } from "@/contexts/sales/domain";
|
||||||
|
import {
|
||||||
|
AggregateRoot,
|
||||||
|
CurrencyData,
|
||||||
|
IDomainError,
|
||||||
|
Language,
|
||||||
|
Name,
|
||||||
|
Note,
|
||||||
|
Result,
|
||||||
|
UniqueID,
|
||||||
|
} from "@shared/contexts";
|
||||||
|
|
||||||
export interface IProfileProps {
|
export interface IProfileProps {
|
||||||
contactInformation: string;
|
name: Name;
|
||||||
defaultPaymentMethod: string;
|
language: Language;
|
||||||
defaultNotes: string;
|
status: DealerStatus;
|
||||||
defaultLegalTerms: string;
|
currency: CurrencyData;
|
||||||
defaultQuoteValidity: string;
|
|
||||||
|
contactInformation: Note;
|
||||||
|
defaultPaymentMethod: Note;
|
||||||
|
defaultNotes: Note;
|
||||||
|
defaultLegalTerms: Note;
|
||||||
|
defaultQuoteValidity: Note;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProfile {
|
export interface IProfile {
|
||||||
id: UniqueID;
|
id: UniqueID;
|
||||||
contactInformation: string;
|
name: Name;
|
||||||
defaultPaymentMethod: string;
|
language: Language;
|
||||||
defaultNotes: string;
|
status: DealerStatus;
|
||||||
defaultLegalTerms: string;
|
currency: CurrencyData;
|
||||||
defaultQuoteValidity: string;
|
|
||||||
|
contactInformation: Note;
|
||||||
|
defaultPaymentMethod: Note;
|
||||||
|
defaultNotes: Note;
|
||||||
|
defaultLegalTerms: Note;
|
||||||
|
defaultQuoteValidity: Note;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Profile extends AggregateRoot<IProfileProps> implements IProfile {
|
export class Profile extends AggregateRoot<IProfileProps> implements IProfile {
|
||||||
@ -23,23 +43,39 @@ export class Profile extends AggregateRoot<IProfileProps> implements IProfile {
|
|||||||
return Result.ok<Profile>(profile);
|
return Result.ok<Profile>(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
get contactInformation(): string {
|
get name(): Name {
|
||||||
|
return this.props.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
get language(): Language {
|
||||||
|
return this.props.language;
|
||||||
|
}
|
||||||
|
|
||||||
|
get status(): DealerStatus {
|
||||||
|
return this.props.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currency(): CurrencyData {
|
||||||
|
return this.props.currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
get contactInformation(): Note {
|
||||||
return this.props.contactInformation;
|
return this.props.contactInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
get defaultPaymentMethod(): string {
|
get defaultPaymentMethod(): Note {
|
||||||
return this.props.defaultPaymentMethod;
|
return this.props.defaultPaymentMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
get defaultNotes(): string {
|
get defaultNotes(): Note {
|
||||||
return this.props.defaultNotes;
|
return this.props.defaultNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
get defaultLegalTerms(): string {
|
get defaultLegalTerms(): Note {
|
||||||
return this.props.defaultLegalTerms;
|
return this.props.defaultLegalTerms;
|
||||||
}
|
}
|
||||||
|
|
||||||
get defaultQuoteValidity(): string {
|
get defaultQuoteValidity(): Note {
|
||||||
return this.props.defaultQuoteValidity;
|
return this.props.defaultQuoteValidity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export class ProfileRepository extends SequelizeRepository<Profile> implements I
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getByUserId(userId: UniqueID): Promise<Profile | null> {
|
public async getByUserId(userId: UniqueID): Promise<Profile | null> {
|
||||||
const rawDealer: any = await this._getBy("Profile_Model", "user_id", userId.toPrimitive());
|
const rawDealer: any = await this._getBy("Dealer_Model", "user_id", userId.toPrimitive());
|
||||||
|
|
||||||
if (!rawDealer === true) {
|
if (!rawDealer === true) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases";
|
import { IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases";
|
||||||
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
||||||
import { User } from "@/contexts/users/domain/entities/User";
|
|
||||||
import { IGetProfileResponse_DTO } from "@shared/contexts";
|
import { IGetProfileResponse_DTO } from "@shared/contexts";
|
||||||
|
|
||||||
|
import { AuthUser } from "@/contexts/auth/domain";
|
||||||
import { IServerError } from "@/contexts/common/domain/errors";
|
import { IServerError } from "@/contexts/common/domain/errors";
|
||||||
import { IInfrastructureError, InfrastructureError } from "@/contexts/common/infrastructure";
|
import { IInfrastructureError, InfrastructureError } from "@/contexts/common/infrastructure";
|
||||||
import { GetProfileUseCase } from "@/contexts/profile/application/GetProfile.useCase";
|
import { GetProfileUseCase } from "@/contexts/profile/application/GetProfile.useCase";
|
||||||
@ -30,7 +30,7 @@ export class GetProfileController extends ExpressController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async executeImpl(): Promise<any> {
|
async executeImpl(): Promise<any> {
|
||||||
const user = <User | undefined>this.req.user;
|
const user = <AuthUser>this.req.user;
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
const errorMessage = "Unexpected missing user data";
|
const errorMessage = "Unexpected missing user data";
|
||||||
@ -42,17 +42,17 @@ export class GetProfileController extends ExpressController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await this.useCase.execute({
|
const profileOrError = await this.useCase.execute({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.isFailure) {
|
if (profileOrError.isFailure) {
|
||||||
return this._handleExecuteError(result.error);
|
return this._handleExecuteError(profileOrError.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const profile = result.object;
|
const profile = profileOrError.object;
|
||||||
|
|
||||||
return this.ok<IGetProfileResponse_DTO>(this.presenter.map(profile, this.context));
|
return this.ok<IGetProfileResponse_DTO>(this.presenter.map(profile, user, this.context));
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
return this.fail(e as IServerError);
|
return this.fail(e as IServerError);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,32 @@
|
|||||||
|
import { AuthUser } from "@/contexts/auth/domain";
|
||||||
import { Profile } from "@/contexts/profile/domain";
|
import { Profile } from "@/contexts/profile/domain";
|
||||||
import { IProfileContext } from "@/contexts/profile/infrastructure/Profile.context";
|
import { IProfileContext } from "@/contexts/profile/infrastructure/Profile.context";
|
||||||
import { IGetProfileResponse_DTO } from "@shared/contexts";
|
import { IGetProfileResponse_DTO } from "@shared/contexts";
|
||||||
|
|
||||||
export interface IGetProfilePresenter {
|
export interface IGetProfilePresenter {
|
||||||
map: (profile: Profile, context: IProfileContext) => IGetProfileResponse_DTO;
|
map: (profile: Profile, user: AuthUser, context: IProfileContext) => IGetProfileResponse_DTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GetProfilePresenter: IGetProfilePresenter = {
|
export const GetProfilePresenter: IGetProfilePresenter = {
|
||||||
map: (profile: Profile, context: IProfileContext): IGetProfileResponse_DTO => {
|
map: (profile: Profile, user: AuthUser, context: IProfileContext): IGetProfileResponse_DTO => {
|
||||||
return {
|
return {
|
||||||
dealer_id: profile.id.toString(),
|
name: user.name.toString(),
|
||||||
contact_information: profile.contactInformation,
|
email: user.email.toString(),
|
||||||
default_payment_method: profile.defaultPaymentMethod,
|
lang_code: user.language.code,
|
||||||
default_notes: profile.defaultNotes,
|
roles: user.getRolesArray(),
|
||||||
default_legal_terms: profile.defaultLegalTerms,
|
dealer: {
|
||||||
default_quote_validity: profile.defaultQuoteValidity,
|
id: profile.id.toString(),
|
||||||
|
name: profile.name.toString(),
|
||||||
|
status: profile.status.toString(),
|
||||||
|
lang_code: profile.language.toString(),
|
||||||
|
currency_code: profile.currency.toString(),
|
||||||
|
|
||||||
|
contact_information: profile.contactInformation.toString(),
|
||||||
|
default_payment_method: profile.defaultPaymentMethod.toString(),
|
||||||
|
default_notes: profile.defaultNotes.toString(),
|
||||||
|
default_legal_terms: profile.defaultLegalTerms.toString(),
|
||||||
|
default_quote_validity: profile.defaultQuoteValidity.toString(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,7 +3,9 @@ import {
|
|||||||
MapperParamsType,
|
MapperParamsType,
|
||||||
SequelizeMapper,
|
SequelizeMapper,
|
||||||
} from "@/contexts/common/infrastructure";
|
} from "@/contexts/common/infrastructure";
|
||||||
import { UniqueID } from "@shared/contexts";
|
import { DealerStatus } from "@/contexts/sales/domain";
|
||||||
|
import { Dealer_Model } from "@/contexts/sales/infrastructure/sequelize";
|
||||||
|
import { CurrencyData, Language, Name, Note, UniqueID } from "@shared/contexts";
|
||||||
import { IProfileProps, Profile } from "../../domain";
|
import { IProfileProps, Profile } from "../../domain";
|
||||||
import { IProfileContext } from "../Profile.context";
|
import { IProfileContext } from "../Profile.context";
|
||||||
import { ProfileCreationAttributes, Profile_Model } from "../sequelize";
|
import { ProfileCreationAttributes, Profile_Model } from "../sequelize";
|
||||||
@ -19,13 +21,29 @@ class ProfileMapper
|
|||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected toDomainMappingImpl(source: Profile_Model, params: any): Profile {
|
protected toDomainMappingImpl(source: Dealer_Model, params: any): Profile {
|
||||||
|
const name = this.mapsValue(source, "name", Name.create);
|
||||||
|
const status = this.mapsValue(source, "status", DealerStatus.create);
|
||||||
|
const language = this.mapsValue(source, "lang_code", Language.createFromCode);
|
||||||
|
const currency = this.mapsValue(source, "currency_code", CurrencyData.createFromCode);
|
||||||
|
|
||||||
|
const contactInformation = this.mapsValue(source, "contact_information", Note.create);
|
||||||
|
const defaultPaymentMethod = this.mapsValue(source, "default_payment_method", Note.create);
|
||||||
|
const defaultNotes = this.mapsValue(source, "default_notes", Note.create);
|
||||||
|
const defaultLegalTerms = this.mapsValue(source, "default_legal_terms", Note.create);
|
||||||
|
const defaultQuoteValidity = this.mapsValue(source, "default_quote_validity", Note.create);
|
||||||
|
|
||||||
const props: IProfileProps = {
|
const props: IProfileProps = {
|
||||||
contactInformation: source.contact_information,
|
name,
|
||||||
defaultPaymentMethod: source.default_payment_method,
|
status,
|
||||||
defaultNotes: source.default_notes,
|
language,
|
||||||
defaultLegalTerms: source.default_legal_terms,
|
currency,
|
||||||
defaultQuoteValidity: source.default_quote_validity,
|
|
||||||
|
contactInformation,
|
||||||
|
defaultPaymentMethod,
|
||||||
|
defaultNotes,
|
||||||
|
defaultLegalTerms,
|
||||||
|
defaultQuoteValidity,
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = this.mapsValue(source, "id", UniqueID.create);
|
const id = this.mapsValue(source, "id", UniqueID.create);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
AggregateRoot,
|
AggregateRoot,
|
||||||
|
CurrencyData,
|
||||||
IDomainError,
|
IDomainError,
|
||||||
KeyValueMap,
|
KeyValueMap,
|
||||||
Language,
|
Language,
|
||||||
@ -12,10 +13,11 @@ import { DealerStatus } from "./DealerStatus";
|
|||||||
export interface IDealerProps {
|
export interface IDealerProps {
|
||||||
user_id: UniqueID;
|
user_id: UniqueID;
|
||||||
name: Name;
|
name: Name;
|
||||||
logo: string;
|
//logo: string;
|
||||||
language: Language;
|
language: Language;
|
||||||
additionalInfo: KeyValueMap;
|
additionalInfo: KeyValueMap;
|
||||||
status: DealerStatus;
|
status: DealerStatus;
|
||||||
|
currency: CurrencyData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDealer {
|
export interface IDealer {
|
||||||
@ -26,6 +28,7 @@ export interface IDealer {
|
|||||||
|
|
||||||
additionalInfo: KeyValueMap;
|
additionalInfo: KeyValueMap;
|
||||||
status: DealerStatus;
|
status: DealerStatus;
|
||||||
|
currency: CurrencyData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Dealer extends AggregateRoot<IDealerProps> implements IDealer {
|
export class Dealer extends AggregateRoot<IDealerProps> implements IDealer {
|
||||||
@ -53,4 +56,8 @@ export class Dealer extends AggregateRoot<IDealerProps> implements IDealer {
|
|||||||
get additionalInfo(): KeyValueMap {
|
get additionalInfo(): KeyValueMap {
|
||||||
return this.props.additionalInfo;
|
return this.props.additionalInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get currency(): CurrencyData {
|
||||||
|
return this.props.currency;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import {
|
|||||||
MapperParamsType,
|
MapperParamsType,
|
||||||
SequelizeMapper,
|
SequelizeMapper,
|
||||||
} from "@/contexts/common/infrastructure";
|
} from "@/contexts/common/infrastructure";
|
||||||
import { KeyValueMap, Language, Name, UniqueID } from "@shared/contexts";
|
import { CurrencyData, KeyValueMap, Language, Name, UniqueID } from "@shared/contexts";
|
||||||
import { Dealer, DealerStatus, IDealerProps } from "../../domain/entities";
|
import { Dealer, DealerStatus, IDealerProps } from "../../domain/entities";
|
||||||
import { ISalesContext } from "../Sales.context";
|
import { ISalesContext } from "../Sales.context";
|
||||||
import { DealerCreationAttributes, Dealer_Model } from "../sequelize";
|
import { DealerCreationAttributes, Dealer_Model } from "../sequelize";
|
||||||
@ -24,6 +24,7 @@ class DealerMapper
|
|||||||
const user_id = this.mapsValue(source, "user_id", UniqueID.create);
|
const user_id = this.mapsValue(source, "user_id", UniqueID.create);
|
||||||
const status = this.mapsValue(source, "status", DealerStatus.create);
|
const status = this.mapsValue(source, "status", DealerStatus.create);
|
||||||
const language = this.mapsValue(source, "lang_code", Language.createFromCode);
|
const language = this.mapsValue(source, "lang_code", Language.createFromCode);
|
||||||
|
const currency = this.mapsValue(source, "currency_code", CurrencyData.createFromCode);
|
||||||
|
|
||||||
const additionalInfoOrError = KeyValueMap.create([
|
const additionalInfoOrError = KeyValueMap.create([
|
||||||
["contact_information", source.contact_information],
|
["contact_information", source.contact_information],
|
||||||
@ -35,10 +36,11 @@ class DealerMapper
|
|||||||
|
|
||||||
const props: IDealerProps = {
|
const props: IDealerProps = {
|
||||||
user_id,
|
user_id,
|
||||||
logo: "",
|
//logo: "",
|
||||||
name,
|
name,
|
||||||
status,
|
status,
|
||||||
language,
|
language,
|
||||||
|
currency,
|
||||||
additionalInfo: additionalInfoOrError.object,
|
additionalInfo: additionalInfoOrError.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,7 +59,8 @@ class DealerMapper
|
|||||||
id: source.id.toPrimitive(),
|
id: source.id.toPrimitive(),
|
||||||
user_id: source.user_id.toPrimitive(),
|
user_id: source.user_id.toPrimitive(),
|
||||||
//contact_id: undefined,
|
//contact_id: undefined,
|
||||||
logo: "",
|
currency_code: source.currency.toPrimitive(),
|
||||||
|
//logo: "",
|
||||||
name: source.name.toPrimitive(),
|
name: source.name.toPrimitive(),
|
||||||
status: source.status.toPrimitive(),
|
status: source.status.toPrimitive(),
|
||||||
lang_code: source.language.toPrimitive(),
|
lang_code: source.language.toPrimitive(),
|
||||||
|
|||||||
@ -55,6 +55,7 @@ export class Dealer_Model extends Model<
|
|||||||
declare default_quote_validity: CreationOptional<string>;
|
declare default_quote_validity: CreationOptional<string>;
|
||||||
declare status: CreationOptional<string>;
|
declare status: CreationOptional<string>;
|
||||||
declare lang_code: CreationOptional<string>;
|
declare lang_code: CreationOptional<string>;
|
||||||
|
declare currency_code: CreationOptional<string>;
|
||||||
|
|
||||||
declare user: NonAttribute<User_Model>;
|
declare user: NonAttribute<User_Model>;
|
||||||
declare quotes: NonAttribute<Quote_Model>;
|
declare quotes: NonAttribute<Quote_Model>;
|
||||||
@ -90,6 +91,12 @@ export default (sequelize: Sequelize) => {
|
|||||||
defaultValue: "es",
|
defaultValue: "es",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
currency_code: {
|
||||||
|
type: new DataTypes.STRING(3),
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: "EUR",
|
||||||
|
},
|
||||||
|
|
||||||
status: {
|
status: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { checkUser, createLoginController } from "@/contexts/auth";
|
import { checkUser, createLoginController } from "@/contexts/auth";
|
||||||
import { createIdentityController } from "@/contexts/auth/infrastructure/express/controllers/identity";
|
|
||||||
import Express from "express";
|
import Express from "express";
|
||||||
import passport from "passport";
|
import passport from "passport";
|
||||||
|
|
||||||
@ -27,12 +26,15 @@ export const authRouter = (appRouter: Express.Router) => {
|
|||||||
|
|
||||||
authRoutes.post("/register");
|
authRoutes.post("/register");
|
||||||
|
|
||||||
|
/*
|
||||||
|
-> Sustituido por /profile
|
||||||
|
|
||||||
authRoutes.get(
|
authRoutes.get(
|
||||||
"/identity",
|
"/identity",
|
||||||
checkUser,
|
checkUser,
|
||||||
(req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
|
(req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
|
||||||
createIdentityController(res.locals["context"]).execute(req, res, next)
|
createIdentityController(res.locals["context"]).execute(req, res, next)
|
||||||
);
|
);*/
|
||||||
|
|
||||||
appRouter.use("/auth", authRoutes);
|
appRouter.use("/auth", authRoutes);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,6 +2,6 @@ export interface IIdentity_Response_DTO {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
language: string;
|
lang_code: string;
|
||||||
roles: string[];
|
roles: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,18 @@
|
|||||||
export interface IGetProfileResponse_DTO {
|
export interface IGetProfileResponse_DTO {
|
||||||
dealer_id: string;
|
name: string;
|
||||||
contact_information: string;
|
email: string;
|
||||||
default_payment_method: string;
|
lang_code: string;
|
||||||
default_notes: string;
|
roles: string[];
|
||||||
default_legal_terms: string;
|
dealer: {
|
||||||
default_quote_validity: string;
|
id: string;
|
||||||
|
name: string;
|
||||||
|
contact_information: string;
|
||||||
|
default_payment_method: string;
|
||||||
|
default_notes: string;
|
||||||
|
default_legal_terms: string;
|
||||||
|
default_quote_validity: string;
|
||||||
|
status: string;
|
||||||
|
lang_code: string;
|
||||||
|
currency_code: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user