feat: add public employee profile view and implement ratings review page components

This commit is contained in:
2026-07-22 16:27:46 -03:00
parent 279e1b54cc
commit dd3e07311d
27 changed files with 1621 additions and 304 deletions
+278 -260
View File
@@ -59,6 +59,7 @@ import { useParams } from "next/navigation";
import dayjs from "dayjs";
import { useConfirmStore } from "@core/Store/Confirm.Store";
import ReviewsCarousel from "@core/app/components/ReviewsCarousel/ReviewsCarousel";
import OrganizationProfessionals from "@core/app/components/OrganizationProfessionals/OrganizationProfessionals";
import { RatingTargetType } from "@core/Models/Ratings.model";
enum VIEW {
@@ -337,7 +338,7 @@ export default function OrganizationPublicProfile() {
return response.data;
}
const newPosts = response.data.filter(
(newPost) => !prevPosts.some((prevPost) => prevPost._id === newPost._id)
(newPost) => !prevPosts.some((prevPost) => prevPost._id === newPost._id),
);
return [...prevPosts, ...newPosts];
@@ -453,7 +454,7 @@ export default function OrganizationPublicProfile() {
eventHandler.setEventType(EVENT_TYPES.SLEEP);
});
},
() => {}
() => {},
);
};
@@ -597,292 +598,309 @@ export default function OrganizationPublicProfile() {
<div className={style.organizationProfileColumns}>
<div className={style.organizationMap}>{LocationInfo(orgData)}</div>
<div className={style.organizationMainColumn}>
<div
ref={refDivContent}
style={{
border: "1px solid var(--gray-light)",
borderRadius: "10px",
marginTop: "30px",
width: "100%",
marginBottom: "30px",
backgroundColor: "var(--white)",
}}
>
<div
ref={refDivContent}
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
borderBottom: "1px solid var(--gray-light)",
border: "1px solid var(--gray-light)",
borderRadius: "10px",
marginTop: "30px",
width: "100%",
marginBottom: "30px",
backgroundColor: "var(--white)",
}}
>
<div
style={{
height: "50px",
display: "flex",
alignItems: "center",
gap: "20px",
}}
>
<div
style={getHeaderItemStyle(VIEW.POSTS)}
onClick={() => {
setView(VIEW.POSTS);
processAddButton(VIEW.POSTS);
}}
>
Posts
</div>
<div
style={getHeaderItemStyle(VIEW.SERVICES)}
onClick={() => {
setView(VIEW.SERVICES);
processAddButton(VIEW.SERVICES);
}}
>
Servicios
</div>
{checkShowInfo() && (
<div
style={getHeaderItemStyle(VIEW.INFO)}
onClick={() => {
setView(VIEW.INFO);
processAddButton(VIEW.INFO);
}}
>
Contacto
</div>
)}
</div>
{view === VIEW.SERVICES && (
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<ButtonGroup
variant="outlined"
aria-label="Basic button group"
sx={{ marginTop: "10px", marginRight: "30px" }}
>
<IconButton onClick={() => setViewMode("card")}>
<GridViewOutlinedIcon
sx={{
color:
viewMode === "card" ? "var(--wine-red)" : "ineherit",
}}
/>
</IconButton>
<IconButton onClick={() => setViewMode("grid")}>
<SplitscreenOutlinedIcon
sx={{
color:
viewMode === "grid" ? "var(--wine-red)" : "ineherit",
}}
/>
</IconButton>
</ButtonGroup>
</div>
)}
</div>
<div>
{view === VIEW.POSTS && (
<div
ref={refPostsContainer}
style={{
overflowY: "scroll",
height: `${getContentHeight()}px`,
}}
>
{showAddButton && (
<div
style={getAddButtonStyle()}
onClick={() => {
setEditorPostId("");
setEditorContent("");
setShowEditor(true);
}}
>
<AddIcon sx={{ fontSize: "32px" }} />
</div>
)}
{posts.length === 0 && (
<div
style={{
textAlign: "center",
backgroundImage: "url(/no-conversation.webp)",
backgroundRepeat: "no-repeat",
backgroundPosition: "center center",
backgroundSize: "50% auto",
height: "100%",
}}
>
Nada por aquí
</div>
)}
{posts.map((post: IPost) => {
return (
<div
key={post._id}
style={{
borderBottom: "1px solid var(--gray-light)",
paddingTop: "5px",
paddingBottom: "10px",
paddingLeft: "30px",
paddingRight: "30px",
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
}}
>
<div style={{ color: "var(--gray-darkest)" }}>
{dayjs(post.createdAt).format("DD MMMM YYYY HH:mm")}
</div>
{post.fixed && (
<div
style={{
color: "var(--gray-light)",
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
>
<PinIcon fontSize="small" />
<span>Anclado</span>
</div>
)}
</div>
<div
dangerouslySetInnerHTML={{
__html: preprocessQuillHtml(
transformQuillContentForDisplay(post.content)
),
}}
/>
{checkPostButtons() && (
<div
style={{
marginTop: "10px",
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "flex-end",
flexWrap: "wrap",
color: "var(--gray-darkest)",
}}
>
<ThemeProvider theme={turnosXpressTheme}>
<MaterialButton
color="inherit"
startIcon={<ClipIcon />}
onClick={() => {
fijarPost(`${post._id}`);
}}
>
{post.fixed ? "Liberar" : "Fijar"}
</MaterialButton>
{post.fixed && (
<>
<MaterialButton
color="inherit"
startIcon={<UpIcon />}
onClick={() => {
moverPost(`${post._id}`, -1);
}}
>
Subir
</MaterialButton>
<MaterialButton
color="inherit"
startIcon={<DownIcon />}
onClick={() => {
moverPost(`${post._id}`, 1);
}}
>
Bajar
</MaterialButton>
</>
)}
<MaterialButton
color="inherit"
onClick={() => {
editarPost(`${post._id}`);
}}
>
<EditIcon />
</MaterialButton>
<MaterialButton
color="inherit"
onClick={() => {
eliminarPost(`${post._id}`);
}}
>
<DeleteIcon />
</MaterialButton>
</ThemeProvider>
</div>
)}
</div>
);
})}
</div>
)}
{view === VIEW.SERVICES && (
<div
className={style.organizationServices}
style={{
overflowY: "scroll",
height: `${getContentHeight()}px`,
flexDirection: "row",
justifyContent: "space-between",
borderBottom: "1px solid var(--gray-light)",
}}
>
<div
style={{
padding: "0px 0px 40px 0px",
height: "50px",
display: "flex",
flexDirection: viewMode === "card" ? "row" : "column",
justifyContent: "start",
alignItems: "center",
gap: "20px",
flexWrap: "wrap",
}}
>
{orgData.services.data.map((service) => (
<ProductItem
product={service}
key={service.id}
width={260}
viewMode={viewMode}
/>
))}
<div
style={getHeaderItemStyle(VIEW.POSTS)}
onClick={() => {
setView(VIEW.POSTS);
processAddButton(VIEW.POSTS);
}}
>
Posts
</div>
<div
style={getHeaderItemStyle(VIEW.SERVICES)}
onClick={() => {
setView(VIEW.SERVICES);
processAddButton(VIEW.SERVICES);
}}
>
Servicios
</div>
{checkShowInfo() && (
<div
style={getHeaderItemStyle(VIEW.INFO)}
onClick={() => {
setView(VIEW.INFO);
processAddButton(VIEW.INFO);
}}
>
Contacto
</div>
)}
</div>
{view === VIEW.SERVICES && (
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<ButtonGroup
variant="outlined"
aria-label="Basic button group"
sx={{ marginTop: "10px", marginRight: "30px" }}
>
<IconButton onClick={() => setViewMode("card")}>
<GridViewOutlinedIcon
sx={{
color:
viewMode === "card"
? "var(--wine-red)"
: "ineherit",
}}
/>
</IconButton>
<IconButton onClick={() => setViewMode("grid")}>
<SplitscreenOutlinedIcon
sx={{
color:
viewMode === "grid"
? "var(--wine-red)"
: "ineherit",
}}
/>
</IconButton>
</ButtonGroup>
</div>
)}
</div>
)}
{view === VIEW.INFO && checkShowInfo() && (
<div
className={style.organizationMoreInfo}
style={{
overflowY: "auto",
}}
>
{LocationInfo(orgData)}
<div>
{view === VIEW.POSTS && (
<div
ref={refPostsContainer}
style={{
overflowY: "scroll",
height: `${getContentHeight()}px`,
}}
>
{showAddButton && (
<div
style={getAddButtonStyle()}
onClick={() => {
setEditorPostId("");
setEditorContent("");
setShowEditor(true);
}}
>
<AddIcon sx={{ fontSize: "32px" }} />
</div>
)}
{posts.length === 0 && (
<div
style={{
textAlign: "center",
backgroundImage: "url(/no-conversation.webp)",
backgroundRepeat: "no-repeat",
backgroundPosition: "center center",
backgroundSize: "50% auto",
height: "100%",
}}
>
Nada por aquí
</div>
)}
{posts.map((post: IPost) => {
return (
<div
key={post._id}
style={{
borderBottom: "1px solid var(--gray-light)",
paddingTop: "5px",
paddingBottom: "10px",
paddingLeft: "30px",
paddingRight: "30px",
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
}}
>
<div style={{ color: "var(--gray-darkest)" }}>
{dayjs(post.createdAt).format(
"DD MMMM YYYY HH:mm",
)}
</div>
{post.fixed && (
<div
style={{
color: "var(--gray-light)",
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
>
<PinIcon fontSize="small" />
<span>Anclado</span>
</div>
)}
</div>
<div
dangerouslySetInnerHTML={{
__html: preprocessQuillHtml(
transformQuillContentForDisplay(
post.content,
),
),
}}
/>
{checkPostButtons() && (
<div
style={{
marginTop: "10px",
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "flex-end",
flexWrap: "wrap",
color: "var(--gray-darkest)",
}}
>
<ThemeProvider theme={turnosXpressTheme}>
<MaterialButton
color="inherit"
startIcon={<ClipIcon />}
onClick={() => {
fijarPost(`${post._id}`);
}}
>
{post.fixed ? "Liberar" : "Fijar"}
</MaterialButton>
{post.fixed && (
<>
<MaterialButton
color="inherit"
startIcon={<UpIcon />}
onClick={() => {
moverPost(
`${post._id}`,
-1,
);
}}
>
Subir
</MaterialButton>
<MaterialButton
color="inherit"
startIcon={<DownIcon />}
onClick={() => {
moverPost(
`${post._id}`,
1,
);
}}
>
Bajar
</MaterialButton>
</>
)}
<MaterialButton
color="inherit"
onClick={() => {
editarPost(`${post._id}`);
}}
>
<EditIcon />
</MaterialButton>
<MaterialButton
color="inherit"
onClick={() => {
eliminarPost(`${post._id}`);
}}
>
<DeleteIcon />
</MaterialButton>
</ThemeProvider>
</div>
)}
</div>
);
})}
</div>
)}
{view === VIEW.SERVICES && (
<div
className={style.organizationServices}
style={{
overflowY: "scroll",
height: `${getContentHeight()}px`,
}}
>
<div
style={{
padding: "0px 0px 40px 0px",
display: "flex",
flexDirection: viewMode === "card" ? "row" : "column",
justifyContent: "start",
gap: "20px",
flexWrap: "wrap",
}}
>
{orgData.services.data.map((service) => (
<ProductItem
product={service}
key={service.id}
width={260}
viewMode={viewMode}
/>
))}
</div>
</div>
)}
{view === VIEW.INFO && checkShowInfo() && (
<div
className={style.organizationMoreInfo}
style={{
overflowY: "auto",
}}
>
{LocationInfo(orgData)}
</div>
)}
</div>
)}
</div>
</div>
</div>
</div>
</div>
{orgData.showPublicOpinions !== false && (
<ReviewsCarousel
targetType={RatingTargetType.COMPANY}
targetId={orgData.id}
title="Lo que dicen quienes ya visitaron esta organización"
title={`Opiniones sobre ${orgData.name}`}
subtitle="Opiniones reales de personas que reservaron turnos acá."
className={style.organizationReviews}
/>
)}
{orgData.showPublicProfessionals !== false && (
<OrganizationProfessionals companyId={orgData.id} />
)}
</div>
)}
</>