Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/Sorting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface OrderItem {

interface Props<T extends string> {
orderByList: Array<OrderItem>;
order: string;
order: 'asc' | 'desc';
setOrder: (s: 'asc' | 'desc') => void;
orderBy: T;
setOrderBy: (s: T) => void;
Expand Down
4 changes: 3 additions & 1 deletion src/components/UI/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const Pagination: FC<PaginationProps> = ({
pageCount,
forcePage,
}) => {
const safeForcePage = pageCount > 0 ? Math.min(forcePage, pageCount - 1) : undefined;

return (
<ReactPaginate
className="flex flex-wrap items-center justify-center gap-2 mt-4 text-gray-500 w-full max-w-full overflow-hidden"
Expand All @@ -21,7 +23,7 @@ export const Pagination: FC<PaginationProps> = ({
previousLabel="← Prev"
pageRangeDisplayed={2}
pageCount={pageCount}
forcePage={forcePage}
forcePage={safeForcePage}
renderOnZeroPageCount={null}
activeClassName="text-brand-500 font-bold px-3 py-2 rounded"
pageClassName="px-2 py-1 sm:px-3 sm:py-2 hover:bg-gray-200"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ declare global {

export const HubspotForm = () => {
useEffect(() => {
const enabled = String(import.meta.env.VITE_HUBSPOT_ENABLED || '').toLowerCase() === 'true';
const portalId = String(import.meta.env.VITE_HUBSPOT_PORTAL_ID || '').trim();
const formId = String(import.meta.env.VITE_HUBSPOT_FORM_ID_TUTORIAL || '').trim();
const region = String(import.meta.env.VITE_HUBSPOT_REGION || 'na1').trim();

// Enterprise/self-hosted safety: do not load HubSpot unless explicitly enabled + configured
if (!enabled || !portalId || !formId) return;

const script = document.createElement('script');
script.src = 'https://js.hsforms.net/forms/embed/v2.js';
script.async = true;
Expand All @@ -25,9 +33,9 @@ export const HubspotForm = () => {
script.onload = () => {
if (window.hbspt) {
window.hbspt.forms.create({
region: 'na1',
portalId: '4732608',
formId: '86cdc2e8-2221-44b0-a926-02bec92c1bed',
region,
portalId,
formId,
target: '#hubspot-form-wrapper'
});
}
Expand Down
20 changes: 18 additions & 2 deletions src/hooks/useCentrifuge.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { useEffect, useState } from 'react';
import { Centrifuge } from 'centrifuge';
import { useAppStore } from '../store/useAppStore';import { refreshToken } from '../http';
import { refreshToken } from '../http';
import { useAppStore } from '../store/useAppStore';

const VITE_APP_CENTRIFUGE_SERVICE = import.meta.env.VITE_APP_CENTRIFUGE_SERVICE;
function getDefaultCentrifugeEndpoint() {
if (typeof window === 'undefined') {
return '';
}

const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
return `${protocol}//${window.location.host}/connection/websocket`;
}

const VITE_APP_CENTRIFUGE_SERVICE =
import.meta.env.VITE_APP_CENTRIFUGE_SERVICE || getDefaultCentrifugeEndpoint();

type CounterType =
| 'counter_chats'
Expand Down Expand Up @@ -32,6 +43,11 @@ export function useCentrifugeChannel() {
}

useEffect(() => {
if (!VITE_APP_CENTRIFUGE_SERVICE) {
setConnected(false);
return;
}

const token = currentUser?.wsToken;

const centrifuge = new Centrifuge(VITE_APP_CENTRIFUGE_SERVICE, {
Expand Down
4 changes: 1 addition & 3 deletions src/pages/AdminApps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default function AdminApps() {
[searchParams]
);
const orderBy = useMemo(
() => (searchParams.get('orderBy') as OrderByType) || 'totalRegistered',
() => (searchParams.get('orderBy') as OrderByType) || 'createdAt',
[searchParams]
);

Expand Down Expand Up @@ -173,8 +173,6 @@ export default function AdminApps() {
setShowModal(!apps.length);
}, [apps.length]);

console.log('newShowModal', newShowModal);

useEffect(() => {
fetchApps();
}, [fetchApps]);
Expand Down
28 changes: 15 additions & 13 deletions src/pages/AuthPage/FacebookButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import CustomButton from './Button.tsx';
import { getUserCredsFromFacebook } from './firebase';
import FacebookIcon from './Icons/socials/facebookIcon';

const HUBSPOT_ENABLED = String(import.meta.env.VITE_HUBSPOT_ENABLED || '').toLowerCase() === 'true';
const HUBSPOT_PORTAL_ID = String(import.meta.env.VITE_HUBSPOT_PORTAL_ID || '').trim();
const HUBSPOT_FORM_ID_SIGNUP = String(import.meta.env.VITE_HUBSPOT_FORM_ID_SIGNUP || '').trim();

export const FacebookButton = () => {
const config = useAppStore((s) => s.currentApp);
const navigate = useNavigate();
Expand Down Expand Up @@ -64,20 +68,18 @@ export const FacebookButton = () => {
return;
}

const hubspotData = {
fields: [
{ name: 'firstname', value: firstName },
{ name: 'lastname', value: lastName },
{ name: 'email', value: email },
{ name: 'website', value: website },
],
};
if (HUBSPOT_ENABLED && HUBSPOT_PORTAL_ID && HUBSPOT_FORM_ID_SIGNUP) {
const hubspotData = {
fields: [
{ name: 'firstname', value: firstName },
{ name: 'lastname', value: lastName },
{ name: 'email', value: email },
{ name: 'website', value: website },
],
};

await sendHSFormData(
'4732608',
'1bf4cbda-8d42-4bfc-8015-c41304eabf19',
hubspotData
);
await sendHSFormData(HUBSPOT_PORTAL_ID, HUBSPOT_FORM_ID_SIGNUP, hubspotData);
}
} catch (error) {
console.error(error);
toast.error('Social registration failed');
Expand Down
44 changes: 24 additions & 20 deletions src/pages/AuthPage/GoogleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ import { navigateToUserPage } from '../../utils/navigateToUserPage';
import CustomButton from './Button';
import GoogleIcon from './Icons/socials/googleIcon';

const ROOT_DOMAIN = String(import.meta.env.VITE_ROOT_DOMAIN || '').trim();
function setEthoraUserCookie(value: string) {
const domainPart =
ROOT_DOMAIN && ROOT_DOMAIN !== 'localhost' ? `; domain=.${ROOT_DOMAIN}` : '';
document.cookie = `ethora_user=${value}; path=/${domainPart}; secure; samesite=lax; max-age=604800`;
}

interface GoogleButtonProps {
utm?: string | null;
}
Expand Down Expand Up @@ -79,23 +86,22 @@ export const GoogleButton = ({ utm }: GoogleButtonProps) => {
return;
}

const hubspotData = {
fields: [
{ name: 'firstname', value: firstName },
{ name: 'lastname', value: lastName },
{ name: 'email', value: email },
{ name: 'website', value: website },
],
};

await sendHSFormData(
'4732608',
'1bf4cbda-8d42-4bfc-8015-c41304eabf19',
hubspotData
);
const hubspotEnabled = String(import.meta.env.VITE_HUBSPOT_ENABLED || '').toLowerCase() === 'true';
const portalId = String(import.meta.env.VITE_HUBSPOT_PORTAL_ID || '').trim();
const formId = String(import.meta.env.VITE_HUBSPOT_FORM_ID_SIGNUP || '').trim();
if (hubspotEnabled && portalId && formId) {
const hubspotData = {
fields: [
{ name: 'firstname', value: firstName },
{ name: 'lastname', value: lastName },
{ name: 'email', value: email },
{ name: 'website', value: website },
],
};
await sendHSFormData(portalId, formId, hubspotData);
}

document.cookie =
'ethora_user=accregred; path=/; domain=.ethora.com; secure; samesite=lax; max-age=604800';
setEthoraUserCookie('accregred');
} catch (error) {
console.error(error);
toast.error('Social registration failed');
Expand All @@ -107,8 +113,7 @@ export const GoogleButton = ({ utm }: GoogleButtonProps) => {
loginType
).then(async ({ data }) => {
await actionAfterLogin(data);
document.cookie =
'ethora_user=accregred; path=/; domain=.ethora.com; secure; samesite=lax; max-age=604800';
setEthoraUserCookie('accregred');
localStorage.setItem('newUser', true.toString());

navigateToUserPage(navigate, config?.afterLoginPage);
Expand All @@ -123,8 +128,7 @@ export const GoogleButton = ({ utm }: GoogleButtonProps) => {
logLogin('google', data.user._id);

await actionAfterLogin(data);
document.cookie =
'ethora_user=accregred; path=/; domain=.ethora.com; secure; samesite=lax; max-age=604800';
setEthoraUserCookie('accregred');

navigateToUserPage(navigate, config?.afterLoginPage);
});
Expand Down
11 changes: 8 additions & 3 deletions src/pages/AuthPage/Login/Steps/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ import CustomButton from '../../Button';
import { GoogleButton } from '../../GoogleButton';
import { MetamaskButton } from '../../MetamaskButton';

const ROOT_DOMAIN = String(import.meta.env.VITE_ROOT_DOMAIN || '').trim();
function setEthoraUserCookie(value: string) {
const domainPart =
ROOT_DOMAIN && ROOT_DOMAIN !== 'localhost' ? `; domain=.${ROOT_DOMAIN}` : '';
document.cookie = `ethora_user=${value}; path=/${domainPart}; secure; samesite=lax; max-age=604800`;
}

type Inputs = {
email: string;
password: string;
Expand All @@ -33,10 +40,8 @@ const LoginStep = () => {
httpLoginWithEmail(email, password)
.then(async ({ data }) => {
await actionAfterLogin(data);

logLogin('email', data.user._id);
document.cookie =
'ethora_user=1; path=/; domain=.ethora.com; secure; samesite=lax; max-age=604800';
setEthoraUserCookie('1');

if (config?.afterLoginPage) {
navigateToUserPage(navigate, config.afterLoginPage as string);
Expand Down
10 changes: 8 additions & 2 deletions src/pages/AuthPage/MetamaskButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ import { navigateToUserPage } from '../../utils/navigateToUserPage';
import CustomButton from './Button';
import MetamaskIcon from './Icons/socials/metamaskIcon';

const ROOT_DOMAIN = String(import.meta.env.VITE_ROOT_DOMAIN || '').trim();
function setEthoraUserCookie(value: string) {
const domainPart =
ROOT_DOMAIN && ROOT_DOMAIN !== 'localhost' ? `; domain=.${ROOT_DOMAIN}` : '';
document.cookie = `ethora_user=${value}; path=/${domainPart}; secure; samesite=lax; max-age=604800`;
}

declare global {
interface Window {
ethereum?: any;
Expand Down Expand Up @@ -55,8 +62,7 @@ export const MetamaskButton = ({ utm }: MetamaskButtonProps) => {

toast.success('Successfully logged in with Metamask!');

document.cookie =
'ethora_user=accregred; path=/; domain=.ethora.com; secure; samesite=lax; max-age=604800';
setEthoraUserCookie('accregred');

if (config?.afterLoginPage) {
navigateToUserPage(navigate, config.afterLoginPage as string);
Expand Down
46 changes: 33 additions & 13 deletions src/pages/AuthPage/Register/RegisterForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ import { GoogleButton } from '../GoogleButton';
import { MetamaskButton } from '../MetamaskButton';
import SkeletonLoader from '../SkeletonLoader';

const SITE_KEY = import.meta.env.VITE_SITE_KEY;
const SITE_KEY = (import.meta.env.VITE_SITE_KEY || '').trim();
const TURNSTILE_ENABLED = SITE_KEY.length > 0;
const ROOT_DOMAIN = String(import.meta.env.VITE_ROOT_DOMAIN || '').trim();

function setEthoraUserCookie(value: string) {
const domainPart =
ROOT_DOMAIN && ROOT_DOMAIN !== 'localhost' ? `; domain=.${ROOT_DOMAIN}` : '';
// Keep existing behavior, but avoid hardcoding ethora.com for enterprise/self-hosted installs
document.cookie = `ethora_user=${value}; path=/${domainPart}; secure; samesite=lax; max-age=604800`;
}

interface FirstStepProps {
isSmallDevice?: boolean;
Expand Down Expand Up @@ -129,15 +138,18 @@ const RegisterForm: React.FC<FirstStepProps> = ({ isSmallDevice = false }) => {
const formData = new FormData(formRef.current!);
const cfToken = formData.get('cf-turnstile-response');

if (!cfToken || typeof cfToken !== 'string' || cfToken.trim() === '') {
// Turnstile is optional for enterprise installs; if VITE_SITE_KEY is empty we skip it.
const cfTokenValue =
typeof cfToken === 'string' ? cfToken.trim() : '';
if (TURNSTILE_ENABLED && !cfTokenValue) {
return;
}

try {
await httpRegisterWithEmailV2(
email,
password,
cfToken,
cfTokenValue,
firstName,
lastName,
utmParams || ''
Expand All @@ -160,9 +172,16 @@ const RegisterForm: React.FC<FirstStepProps> = ({ isSmallDevice = false }) => {
return;
}

const hubspotEnabled = String(import.meta.env.VITE_HUBSPOT_ENABLED || '').toLowerCase() === 'true';
const portalId = String(import.meta.env.VITE_HUBSPOT_PORTAL_ID || '').trim();
const formId = String(import.meta.env.VITE_HUBSPOT_FORM_ID_SIGNUP || '').trim();
if (!hubspotEnabled || !portalId || !formId) {
return;
}

await sendHSFormData(
'4732608',
'1bf4cbda-8d42-4bfc-8015-c41304eabf19',
portalId,
formId,
hubspotData
);
});
Expand All @@ -174,8 +193,7 @@ const RegisterForm: React.FC<FirstStepProps> = ({ isSmallDevice = false }) => {

httpLoginWithEmail(email, password)
.then(async ({ data }) => {
document.cookie =
'ethora_user=1; path=/; domain=.ethora.com; secure; samesite=lax; max-age=604800';
setEthoraUserCookie('1');
localStorage.setItem('newUser', true.toString());

await actionAfterLogin(data);
Expand Down Expand Up @@ -311,12 +329,14 @@ const RegisterForm: React.FC<FirstStepProps> = ({ isSmallDevice = false }) => {
helperText={errors.password?.message}
/>
<Box className="flex justify-center items-center">
<Turnstile
options={{
theme: 'light',
}}
siteKey={SITE_KEY}
/>
{TURNSTILE_ENABLED && (
<Turnstile
options={{
theme: 'light',
}}
siteKey={SITE_KEY}
/>
)}
</Box>
<CustomButton
type="submit"
Expand Down
Loading
Loading