first commit

This commit is contained in:
2026-07-16 20:48:43 -03:00
commit 5696cee264
1111 changed files with 322270 additions and 0 deletions
@@ -0,0 +1,17 @@
"use client";
import { PublicOrganizationView } from "@core/Models/Company.model";
import { useOrgDataStore } from "@core/Store/OrganizationData.Store";
import { useEffect } from "react";
export type OrganizationDataProps = {
orgData: PublicOrganizationView;
};
export default function OrganizationDataConnector({ orgData }: OrganizationDataProps) {
const OrganizationData = useOrgDataStore();
useEffect(() => {
OrganizationData.setData(orgData);
}, [orgData]);
return <></>;
}
@@ -0,0 +1,84 @@
import AnimatedContainer from "@components/AnimatedConainer/AnimatedContainer";
import ApiServerService from "@services/Api.Server.Service";
import { PublicOrganizationView } from "@core/Models/Company.model";
import OrganizationHeader from "@core/app/components/Home/OrganizationHeader/OrganizationHeader";
import OrganizationDataConnector from "./components/OrganizationData";
const GetOrganizationData = async (companyId: string): Promise<PublicOrganizationView> => {
try {
const organizationData = await ApiServerService.post<PublicOrganizationView>(
"views/organization",
{
companyId: companyId,
}
);
return organizationData;
} catch {
return {} as PublicOrganizationView;
}
};
type Params = {
oid: string;
};
type Props = {
params: Promise<Params>; // `params` ahora es una Promesa
children: React.ReactNode;
};
export default async function OrganizationPublicProfile({ params, children }: Props) {
const { oid } = await params;
const orgData = await GetOrganizationData(oid);
return (
<AnimatedContainer
color={orgData.headerColor}
minSize={150}
maxSize={500}
items={10}
style={{
background: `linear-gradient(180deg, ${orgData.headerColor} 0%, var(--white) 50%)`,
}}
>
<div className="homeCentered">
{orgData.id && (
<>
<OrganizationHeader organization={orgData} />
<OrganizationDataConnector orgData={orgData} />
<div>{children}</div>
</>
)}
{!orgData.id && (
<div
style={{
backgroundImage: `url(/no-org-slug.webp)`,
backgroundRepeat: "no-repeat",
backgroundPosition: "center center",
backgroundSize: "50% auto",
width: "100%",
height: "750px",
color: "var(--wine-red)",
fontWeight: "600",
fontSize: "26px",
display: "flex",
justifyContent: "center",
alignItems: "flex-end",
marginTop: "10px",
marginBottom: "30px",
textAlign: "center",
paddingLeft: "20px",
paddingRight: "20px",
}}
>
<p style={{ padding: "20px" }}>
La organización que estas buscando no existe
</p>
</div>
)}
</div>
</AnimatedContainer>
);
}
+875
View File
@@ -0,0 +1,875 @@
"use client";
import style from "./profile.module.css";
//import ProductGallery from "@components/Home/ProductsGallery/ProductGallery";
import WhatsAppIcon from "@mui/icons-material/WhatsApp";
import LocationOnIcon from "@mui/icons-material/LocationOn";
import LocationMap from "@core/app/components/LocationMap/LocationMap";
import Button from "@core/app/components/Button/Button";
import { useNavigation } from "@core/app/hooks/goto";
import { useOrgDataStore } from "@core/Store/OrganizationData.Store";
import { useEffect, useRef, useState } from "react";
import { PublicOrganizationView } from "@core/Models/Company.model";
import { blurElementsOnLoad } from "@core/helpers/blur";
import { ButtonGroup, IconButton } from "@mui/material";
import GridViewOutlinedIcon from "@mui/icons-material/GridViewOutlined";
import SplitscreenOutlinedIcon from "@mui/icons-material/SplitscreenOutlined";
import ProductItem, { FindResultsViewMode } from "@core/app/components/ProductItem/ProductItem";
import {
FacebookShareButton,
EmailShareButton,
WhatsappShareButton,
TelegramShareButton,
TwitterShareButton,
FacebookIcon,
WhatsappIcon as WhatsAppShareIcon,
EmailIcon,
TelegramIcon,
TwitterIcon,
} from "react-share";
import HeaderConfProvider from "@core/app/components/HeaderConfProvider/HeaderConfProvider";
import useWindowSize from "@core/app/hooks/WindowSize";
import AddIcon from "@mui/icons-material/AddOutlined";
import CloseIcon from "@mui/icons-material/Close";
import QuillEditor from "@core/app/components/QuillEditor/QuillEditor";
import {
deletePost,
findPostsByOrganization,
getPost,
moveFixedPost,
savePost,
toggleFixedPost,
} from "./post.service";
import { useSessionStore } from "@core/Store/Sesion.Store";
import { EVENT_TYPES, useEventHandlerStore } from "@core/Store/EventHandler.Store";
import { useAlert } from "@core/Store/Alert.Store";
import { IPost } from "@core/Models/Posts.model";
import { preprocessQuillHtml, transformQuillContentForDisplay } from "@core/app/helpers/htmlSainitize";
import { useSearchParams } from "next/navigation";
import { ThemeProvider } from "@emotion/react";
import MaterialButton from "@mui/material/Button";
import ClipIcon from "@mui/icons-material/AttachFileRounded";
import DeleteIcon from "@mui/icons-material/DeleteOutlineRounded";
import UpIcon from "@mui/icons-material/ArrowUpwardRounded";
import DownIcon from "@mui/icons-material/ArrowDownwardRounded";
import PinIcon from "@mui/icons-material/PushPin";
import EditIcon from "@mui/icons-material/AutoFixHigh";
import turnosXpressTheme from "@core/app/theme/turnosXpress";
import { useParams } from "next/navigation";
import dayjs from "dayjs";
import { useConfirmStore } from "@core/Store/Confirm.Store";
enum VIEW {
POSTS = "posts",
SERVICES = "services",
OPINIONS = "opinions",
INFO = "info",
}
type UrlData = {
oid: string;
};
export default function OrganizationPublicProfile() {
const data = useParams<UrlData>();
const oid = data.oid;
const OrganizationData = useOrgDataStore();
const [position, setPosition] = useState<[number, number]>([0, 0]);
const [orgData, setOrgData] = useState<PublicOrganizationView>();
const [viewMode, setViewMode] = useState<FindResultsViewMode>("grid");
const [shareTitle, setShareTitle] = useState<string>("");
const [view, setView] = useState<VIEW>(VIEW.POSTS);
const [wndWidth, wndHeight] = useWindowSize();
const { goTo } = useNavigation();
const refDivContent = useRef<HTMLDivElement>(null);
const refPostsContainer = useRef<HTMLDivElement>(null);
const [showAddButton, setShowAddButton] = useState<boolean>(false);
const [showEditor, setShowEditor] = useState<boolean>(false);
const [firstLoad, setFirstLoad] = useState<boolean>(true);
const [editorPostId, setEditorPostId] = useState<string>("");
const [editorContent, setEditorContent] = useState("");
const [posts, setPosts] = useState<IPost[]>([]);
const [authorizedUsers, setAuthorizedUsers] = useState<string[]>([]);
const [currentPage, setCurrentPage] = useState<number>(1);
const SessionInfo = useSessionStore();
const eventHandler = useEventHandlerStore();
const alert = useAlert();
const confirm = useConfirmStore();
const searchParams = useSearchParams();
const tab = searchParams.get("tab") || "posts";
useEffect(() => {
blurElementsOnLoad();
if (!tab) {
setView(VIEW.POSTS);
return;
}
switch (tab) {
case "posts":
setView(VIEW.POSTS);
break;
case "services":
setView(VIEW.SERVICES);
break;
case "opinions":
setView(VIEW.OPINIONS);
break;
case "info":
setView(VIEW.INFO);
break;
default:
setView(VIEW.POSTS);
break;
}
}, []);
useEffect(() => {
requestAnimationFrame(() => {
setTimeout(() => {
processAddButton();
}, 1000);
});
}, [SessionInfo, authorizedUsers]);
useEffect(() => {
if (!OrganizationData.orgData) return;
if (!oid) return; //if (!OrganizationData.orgData.id) return;
setOrgData(OrganizationData.orgData);
setPosition([OrganizationData.orgData.latitude, OrganizationData.orgData.longitude]);
setShareTitle(OrganizationData.orgData.name + " - " + OrganizationData.orgData.description);
setCurrentPage(1);
setPosts([]);
cargarPosts(OrganizationData.orgData.id, 1);
}, [OrganizationData.orgData]);
useEffect(() => {
if (orgData && oid) {
//if (orgData && orgData.id) {
cargarPosts(orgData.id, currentPage);
}
}, [currentPage, orgData]);
useEffect(() => {
const handleScroll = () => {
if (refPostsContainer.current) {
const { scrollTop, scrollHeight, clientHeight } = refPostsContainer.current;
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 50;
if (isAtBottom) {
setCurrentPage((prevPage) => prevPage + 1);
}
}
};
const currentRef = refPostsContainer.current;
if (currentRef) {
currentRef.addEventListener("scroll", handleScroll);
}
return () => {
if (currentRef) {
currentRef.removeEventListener("scroll", handleScroll);
}
};
}, [refPostsContainer.current, view, currentPage]);
const processAddButton = (currentView: VIEW = view) => {
if (currentView != VIEW.POSTS) {
setShowAddButton(false);
return;
}
if (!SessionInfo.userId) {
setShowAddButton(false);
return;
}
if (!authorizedUsers.includes(SessionInfo.userId)) {
setShowAddButton(false);
return;
}
setShowAddButton(true);
};
const checkPostButtons = (): boolean => {
if (!SessionInfo.userId) {
return false;
}
if (authorizedUsers.includes(SessionInfo.userId)) {
return true;
}
return false;
};
const checkShowInfo = (): boolean => {
if (wndWidth < 800) {
return true;
}
if (view === VIEW.INFO) {
setView(VIEW.POSTS);
}
return false;
};
const getContentHeight = () => {
if (!refDivContent.current) return 0;
const containerSize = refDivContent.current.getClientRects().item(0);
if (!containerSize) return 0;
return wndHeight - containerSize.y - 90;
};
const getHeaderItemStyle = (item: VIEW): React.CSSProperties => {
const returnValue: React.CSSProperties = {};
returnValue.fontWeight = "bold";
returnValue.color = "var(--wine-black)";
returnValue.height = "100%";
returnValue.display = "flex";
returnValue.alignItems = "center";
returnValue.padding = "20px";
returnValue.cursor = "pointer";
if (item === view) {
returnValue.borderBottom = "3px solid var(--wine-red)";
}
return returnValue;
};
const getAddButtonStyle = (): React.CSSProperties => {
const returnValue: React.CSSProperties = {};
const buttonWidth = 64;
const buttonMargin = 40;
returnValue.position = "absolute";
returnValue.backgroundColor = "var(--wine-dark)";
returnValue.width = `${buttonWidth}px`;
returnValue.height = `${buttonWidth}px`;
returnValue.borderRadius = "50%";
returnValue.display = "flex";
returnValue.justifyContent = "center";
returnValue.alignItems = "center";
returnValue.cursor = "pointer";
returnValue.color = "var(--white)";
returnValue.zIndex = 10;
returnValue.right = `${buttonMargin}px`;
returnValue.bottom = `${buttonMargin}px`;
return returnValue;
};
const getEditorStyle = (): React.CSSProperties => {
const returnValue: React.CSSProperties = {};
returnValue.position = "fixed";
returnValue.backgroundColor = "var(--white)";
returnValue.top = "60px";
returnValue.left = "0px";
returnValue.right = "0px";
returnValue.bottom = "0px";
returnValue.color = "var(--black)";
returnValue.zIndex = 9999;
returnValue.display = "flex";
returnValue.flexDirection = "column";
return returnValue;
};
const crearPost = (content: string) => {
setShowEditor(false);
eventHandler.setEventType(EVENT_TYPES.LOADING);
savePost({
content: content,
companyId: orgData!.id,
postId: editorPostId ? editorPostId : undefined,
sessionUser: SessionInfo.userId,
})
.then(() => {
alert.showSuccess("Post creado");
// After creating a post, reset and reload the first page
setCurrentPage(1);
setPosts([]);
if (orgData) {
cargarPosts(orgData.id, 1);
}
})
.catch((error) => {
alert.showError(error.format());
})
.finally(() => {
setEditorContent("");
eventHandler.setEventType(EVENT_TYPES.SLEEP);
});
};
const cargarPosts = (companyId: string, page: number) => {
if (!companyId) {
return;
}
findPostsByOrganization({
companyId: companyId,
page: page,
limit: 10,
sessionUser: SessionInfo.userId,
})
.then((response) => {
setAuthorizedUsers(response.authorizedUsers);
requestAnimationFrame(() => {
setPosts((prevPosts) => {
if (page === 1) {
return response.data;
}
const newPosts = response.data.filter(
(newPost) => !prevPosts.some((prevPost) => prevPost._id === newPost._id)
);
return [...prevPosts, ...newPosts];
});
requestAnimationFrame(() => {
processAddButton();
});
});
if (firstLoad) {
if (view === VIEW.POSTS && response.data.length == 0) {
requestAnimationFrame(() => {
setView(VIEW.SERVICES);
processAddButton();
});
}
}
setFirstLoad(false);
})
.catch((error) => {
console.log(error.format());
alert.showError(error.format());
});
};
const fijarPost = (postId: string) => {
if (!orgData) {
alert.showError("No se pudo determinar la organización.");
return;
}
eventHandler.setEventType(EVENT_TYPES.LOADING);
toggleFixedPost({
companyId: orgData.id,
postId: postId,
sessionUser: SessionInfo.userId,
})
.then(() => {
alert.showSuccess("Post actualizado");
// After creating a post, reset and reload the first page
setCurrentPage(1);
setPosts([]);
if (orgData) {
cargarPosts(oid, 1); //cargarPosts(orgData.id, 1);
}
})
.catch((error) => {
alert.showError(error.format());
})
.finally(() => {
eventHandler.setEventType(EVENT_TYPES.SLEEP);
});
};
const moverPost = (postId: string, moveLength: number) => {
if (!orgData) {
alert.showError("No se pudo determinar la organización.");
return;
}
eventHandler.setEventType(EVENT_TYPES.LOADING);
moveFixedPost({
companyId: orgData.id,
postId: postId,
moveLength: moveLength,
sessionUser: SessionInfo.userId,
})
.then(() => {
alert.showSuccess("Post actualizado");
// After creating a post, reset and reload the first page
setCurrentPage(1);
setPosts([]);
if (orgData) {
cargarPosts(oid, 1); //cargarPosts(orgData.id, 1);
}
})
.catch((error) => {
alert.showError(error.format());
})
.finally(() => {
eventHandler.setEventType(EVENT_TYPES.SLEEP);
});
};
const eliminarPost = (postId: string) => {
if (!orgData) {
alert.showError("No se pudo determinar la organización.");
return;
}
confirm.show(
"¿Estás seguro de eliminar el post?",
() => {
eventHandler.setEventType(EVENT_TYPES.LOADING);
deletePost({
companyId: orgData.id,
id: postId,
sessionUser: SessionInfo.userId,
})
.then(() => {
setPosts((prevPosts) => prevPosts.filter((post) => post._id !== postId));
alert.showSuccess("Post eliminado");
})
.catch((error) => {
alert.showError(error.format());
})
.finally(() => {
eventHandler.setEventType(EVENT_TYPES.SLEEP);
});
},
() => {}
);
};
const editarPost = (postId: string) => {
getPost({
id: postId,
})
.then((postData) => {
setEditorPostId(postId);
setEditorContent(postData.content);
setShowEditor(true);
})
.catch((error) => {
alert.showError(error.format());
});
};
const LocationInfo = (data: PublicOrganizationView | null) => {
if (!data) {
return null;
}
return (
<>
<h2>Información Útil</h2>
<LocationMap position={position} orgData={data} />
<ul>
<li>
<LocationOnIcon />
{data.address}
</li>
<li>
<WhatsAppIcon />
{data.phone}
</li>
</ul>
<Button
color="primary"
text="Enviar mensaje"
width="100%"
onClick={() => {
goTo(`/landing/org/${data.id}/send-message`);
}}
/>
<div
style={{
display: "flex",
justifyContent: "center",
flexDirection: "row",
alignItems: "center",
gap: "10px",
}}
>
<WhatsappShareButton title={shareTitle} separator=":: " url={window.location.href}>
<WhatsAppShareIcon size={32} round />
</WhatsappShareButton>
<FacebookShareButton title={shareTitle} url={window.location.href}>
<FacebookIcon size={32} round />
</FacebookShareButton>
<EmailShareButton title={shareTitle} separator=":: " url={window.location.href}>
<EmailIcon size={32} round />
</EmailShareButton>
<TelegramShareButton title={shareTitle} url={window.location.href}>
<TelegramIcon size={32} round />
</TelegramShareButton>
<TwitterShareButton title={shareTitle} url={window.location.href}>
<TwitterIcon size={32} round />
</TwitterShareButton>
</div>
</>
);
};
return (
<>
<HeaderConfProvider />
{orgData && (
<div className={style.organizationContent}>
{showEditor && (
<div style={getEditorStyle()}>
{/* Header */}
<div
style={{
height: "50px",
backgroundColor: "#f0f0f0",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
paddingLeft: " 20px",
borderBottom: "1px solid #ccc",
}}
>
<h2>Qué estas pensando?</h2>
<IconButton
color="inherit"
style={{ width: "64px", height: "64px" }}
onClick={() => {
setShowEditor(false);
}}
>
<CloseIcon sx={{ ml: 1, mr: 1 }} />
</IconButton>
</div>
{/* Content (Editor) */}
<div
style={{
flexGrow: 1,
display: "flex",
flexDirection: "column",
overflow: "auto",
}}
>
<QuillEditor value={editorContent} onChange={setEditorContent} />
</div>
{/* Bottom Bar */}
<div
style={{
height: "60px",
backgroundColor: "#f0f0f0",
borderTop: "1px solid #ccc",
padding: "0 20px",
display: "flex",
alignItems: "center",
}}
>
<Button
text={editorPostId ? "Actualizar" : "Publicar"}
width="100%"
onClick={() => {
setShowEditor(false);
crearPost(editorContent);
}}
color="success"
></Button>
</div>
</div>
)}
<div className={style.organizationMap}>{LocationInfo(orgData)}</div>
<div
ref={refDivContent}
style={{
border: "1px solid var(--gray-light)",
borderRadius: "10px",
marginTop: "30px",
width: "100%",
marginBottom: "30px",
backgroundColor: "var(--white)",
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
borderBottom: "1px solid var(--gray-light)",
}}
>
<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`,
}}
>
<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>
)}
</>
);
}
@@ -0,0 +1,67 @@
import ApiRequest from "@services/Api.Service";
import * as Yup from "yup";
import { ApiError } from "@core/Models/Server.Error.model";
import {
DeletePostParams,
GetPostParams,
IPost,
PaginatePostsParams,
PaginatePostsResults,
SavePostParams,
} from "@core/Models/Posts.model";
import { FixCompanyPostParams, MoveCompanyFixedPostParams } from "@core/Models/Company.model";
const schemaPostSave = Yup.object().shape({
postId: Yup.string().optional(),
companyId: Yup.string().required("No es posible deteriminar la organización."),
content: Yup.string().required("El post esta vacío."),
fixed: Yup.boolean().optional(),
fixedOrder: Yup.number().optional(),
sessionUser: Yup.string().required("Para crear un descuento debe iniciar sesión."),
});
export const savePost = async (data: SavePostParams): Promise<IPost> => {
let yupErrors: Yup.ValidationError = new Yup.ValidationError("");
const validateData = async () => {
try {
await schemaPostSave.validate(data, { abortEarly: true });
return true;
} catch (error) {
if (error instanceof Yup.ValidationError) {
yupErrors = error as Yup.ValidationError;
}
return false;
}
};
if ((await validateData()) == false) {
throw new ApiError(400, yupErrors.message);
}
return ApiRequest.post<IPost>("posts/save", data);
};
export const findPostsByOrganization = async (
data: PaginatePostsParams
): Promise<PaginatePostsResults> => {
return ApiRequest.post<PaginatePostsResults>("posts/paginate", data);
};
export const getPost = async (
data: GetPostParams
): Promise<IPost> => {
return ApiRequest.post<IPost>("posts/get-post", data);
};
export const deletePost = async (data: DeletePostParams): Promise<void> => {
return ApiRequest.post<void>("posts/delete", data);
};
export const toggleFixedPost = async (data: FixCompanyPostParams): Promise<void> => {
return ApiRequest.post<void>("companies/toggle-fixed-post", data);
};
export const moveFixedPost = async (data: MoveCompanyFixedPostParams): Promise<void> => {
return ApiRequest.post<void>("companies/move-fixed-post", data);
};
@@ -0,0 +1,139 @@
@media (max-width: 800px) {
.organizationContent {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
margin-left: 30px;
margin-right: 30px;
gap: 20px;
overflow: hidden;
}
.organizationMap {
border: solid 1px var(--gray-light);
border-radius: 10px;
background-color: white;
padding: 30px;
width: 100%;
max-width: 400px;
margin-left: auto;
margin-right: auto;
margin-top: 30px;
margin-bottom: 30px;
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
}
.organizationMap ul {
list-style-type: none;
padding: 0px;
margin: 0px;
}
.organizationMap li {
margin: auto;
text-align: center;
font-weight: 500;
color: (--black);
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}
.organizationMoreInfo {
background-color: white;
padding: 30px;
width: 100%;
max-width: 400px;
margin-top: 0px;
margin-bottom: 30px;
margin-left: auto;
margin-right: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
gap: 20px;
}
.organizationMoreInfo ul {
list-style-type: none;
padding: 0px;
margin: 0px;
}
.organizationMoreInfo li {
margin: auto;
text-align: center;
font-weight: 500;
color: (--black);
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}
.organizationServices {
margin-bottom: 30px;
}
}
@media (min-width: 801px) {
.organizationContent {
display: flex;
flex-direction: row;
align-items: flex-start;
/*margin-top: 30px;*/
margin-left: 30px;
margin-right: 30px;
gap: 20px;
}
.organizationMap {
border: solid 1px var(--gray-light);
border-radius: 10px;
background-color: white;
padding: 30px;
width: 100%;
max-width: 400px;
margin-top: 30px;
margin-bottom: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
}
.organizationMap ul {
list-style-type: none;
padding: 0px;
margin: 0px;
}
.organizationMap li {
margin: auto;
text-align: center;
font-weight: 500;
color: (--black);
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}
.organizationServices {
margin-bottom: 30px;
padding-right: 10px;
width: 100%;
overflow: hidden;
}
}
@@ -0,0 +1,87 @@
"use client";
import style from "./style.module.css";
import Textbox from "@core/app/components/Textbox/Textbox";
import Button from "@core/app/components/Button/Button";
import { useOrgDataStore } from "@core/Store/OrganizationData.Store";
import { PublicOrganizationView } from "@core/Models/Company.model";
import { useEffect, useState } from "react";
import { sendMessage } from "@core/app/messenger/Messages.service";
import { MESSAGE_CONVERSATION_TYPES, SendMessageParams } from "@core/Models/Messages.model";
import { useSessionStore } from "@core/Store/Sesion.Store";
import { useAlert } from "@core/Store/Alert.Store";
export default function OrganizationPublicProfile() {
const SessionInfo = useSessionStore();
const alert = useAlert();
const OrganizationData = useOrgDataStore();
const [orgData, setOrgData] = useState<PublicOrganizationView>();
const [comments, setComments] = useState<string>("");
useEffect(() => {
if (!OrganizationData.orgData) return;
setOrgData(OrganizationData.orgData);
}, [OrganizationData.orgData]);
const send = () => {
if (!orgData) return;
const conversationType = MESSAGE_CONVERSATION_TYPES.USER_TO_ORG;
const sendMessageData: SendMessageParams = {
conversationId: undefined,
type: conversationType,
userIdFrom: SessionInfo.userId,
userIdTo: undefined,
companyId: orgData.id,
message: comments,
sessionUser: SessionInfo.userId,
};
sendMessage(sendMessageData)
.then(() => {
alert.showSuccess("Mensaje enviado");
setComments("");
})
.catch((error) => {
alert.showError(error);
});
};
return (
<>
{orgData && (
<div className="homeCentered">
<div className={style.organizationContent}>
<h1 className="homeTitleHeader">Contactate con nosotros</h1>
<p className="homeResumeHeader">
¿Tienes preguntas, sugerencias o necesitas más información? Estás en el
lugar indicado. Aquí puedes ponerte en contacto directamente con nuestro
equipo.{" "}
<b>
Para enviar tu mensaje, es necesario estar registrado en el sitio.{" "}
</b>
Completa el formulario y te responderemos lo antes posible. ¡Será un
placer ayudarte!
</p>
<Textbox
type="comments"
placeholder="Escribe tu mensaje"
value={comments}
width="100%"
style={{ height: "200px" }}
onChange={(e) => setComments(e.target.value)}
/>
<Button
color="primary"
text="Enviar"
width="100%"
style={{ marginTop: "20px", marginBottom: "20px" }}
onClick={send}
/>
</div>
</div>
)}
</>
);
}
@@ -0,0 +1,23 @@
@media (max-width: 800px) {
.organizationContent {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
margin-left: 30px;
margin-right: 30px;
gap: 20px;
overflow: hidden;
}
}
@media (min-width: 801px) {
.organizationContent {
display: flex;
flex-direction: column;
align-items: flex-start;
/*margin-top: 30px;*/
margin-left: 30px;
margin-right: 30px;
}
}