+
+ {React.cloneElement(SlidesSections[sections[sectionIndex]], { key: sections[sectionIndex] })}
+
+
0 ? styles.allButtons : styles.onlyRightButton}>
+ {sectionIndex > 0 && (
+
getPreviousSection()}
+ loading={false}
+ text={"Previous"}
+ variant="tertiary"
+ styles={{ maxWidth: "120px", zIndex: 10 }}
+ />
+ )}
+
+ {sections.map((section) => (
+
setSectionIndex(sections.indexOf(section))}
+ />
+ ))}
+
+
getNextSection()}
+ />
+
+
+
+ );
+};
+
+export default WalkthroughApp;
diff --git a/morpheus-client/components/buttons/ButtonPrimary/ButtonPrimary.module.scss b/morpheus-client/components/buttons/Button/Button.module.scss
similarity index 59%
rename from morpheus-client/components/buttons/ButtonPrimary/ButtonPrimary.module.scss
rename to morpheus-client/components/buttons/Button/Button.module.scss
index 3ef4c2b8..dfc4f4b7 100644
--- a/morpheus-client/components/buttons/ButtonPrimary/ButtonPrimary.module.scss
+++ b/morpheus-client/components/buttons/Button/Button.module.scss
@@ -1,21 +1,21 @@
@use "styles/colors";
@use "styles/media";
-.buttonPrimary {
- width: 526px;
- max-width: 100%;
- height: 48px;
+@mixin buttonBase {
+ cursor: pointer;
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 16px;
- padding: 12px 57px;
- cursor: pointer;
- background: colors.$main-color;
+ width: 526px;
+ max-width: 100%;
border: none;
border-radius: 8px;
+ flex: none;
+ order: 0;
+ flex-grow: 0;
@include media.mobile {
width: 100%;
@@ -29,9 +29,32 @@
align-items: center;
gap: 16px;
}
+}
+
+.buttonPrimary {
+ @include buttonBase;
+ height: 48px;
+ padding: 12px 57px;
+ background: colors.$main-color;
&.disabled {
background: colors.$background-primary-4;
cursor: not-allowed;
}
+}
+
+.buttonSecondary {
+ @include buttonBase;
+ height: 56px;
+ padding: 16px;
+ background: colors.$background-secondary;
+ border: 1px solid colors.$background-border;
+}
+
+.buttonTertiary {
+ @include buttonBase;
+ height: 48px;
+ padding: 16px;
+ background: colors.$background-white;
+ border: 1px solid colors.$background-primary-5;
}
\ No newline at end of file
diff --git a/morpheus-client/components/buttons/Button/Button.tsx b/morpheus-client/components/buttons/Button/Button.tsx
new file mode 100644
index 00000000..a8a9a38d
--- /dev/null
+++ b/morpheus-client/components/buttons/Button/Button.tsx
@@ -0,0 +1,78 @@
+import React, { CSSProperties } from "react";
+import Loader from "../../Loaders/LoaderCircle/Loader";
+import styles from "./Button.module.scss";
+import { cn } from "@/utils/styles";
+
+const buttonVariants = {
+ primary: {
+ button: {
+ active: styles.buttonPrimary,
+ disabled: styles.disabled,
+ },
+ text: {
+ active: "base-1 white",
+ },
+ },
+ secondary: {
+ button: {
+ active: styles.buttonSecondary,
+ disabled: styles.disabled,
+ },
+ text: {
+ active: "base-1 white",
+ },
+ },
+ tertiary: {
+ button: {
+ active: styles.buttonTertiary,
+ disabled: styles.disabled,
+ },
+ text: {
+ active: "base-1",
+ },
+ },
+};
+
+type buttonVariant = keyof typeof buttonVariants;
+
+const getVariantStyle = (variant?: buttonVariant) => {
+ return buttonVariants[variant ? variant : "primary"];
+};
+
+interface ButtonProps {
+ loading: boolean;
+ disabled?: boolean;
+ text: string;
+ onClick: (event?: any) => any;
+ styles?: CSSProperties;
+ className?: any;
+ loaderColor?: string;
+ icon?: any;
+ variant?: buttonVariant;
+}
+
+const Button = (props: ButtonProps) => {
+ return (
+
+ {props.loading ? (
+
+ ) : (
+
+ {props.icon && props.icon}
+ {props.text}
+
+ )}
+
+ );
+};
+
+export default Button;
\ No newline at end of file
diff --git a/morpheus-client/components/buttons/ButtonPrimary/ButtonPrimary.tsx b/morpheus-client/components/buttons/ButtonPrimary/ButtonPrimary.tsx
deleted file mode 100644
index 23e8c264..00000000
--- a/morpheus-client/components/buttons/ButtonPrimary/ButtonPrimary.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React, { CSSProperties } from "react";
-import Loader from "../../Loaders/LoaderCircle/Loader";
-import styles from "./ButtonPrimary.module.scss";
-
-interface ButtonPrimaryProps {
- loading: boolean;
- disabled?: boolean;
- text: string;
- onClick: (event?: any) => any;
- styles?: CSSProperties;
- className?: any;
- loaderColor?: string;
-}
-
-const ButtonPrimary = (props: ButtonPrimaryProps) => {
- return (
-
- {props.loading ? (
-
- ) : (
- {props.text}
- )}
-
- );
-};
-
-export default ButtonPrimary;
diff --git a/morpheus-client/components/buttons/ButtonSecondary/ButtonSecondary.module.scss b/morpheus-client/components/buttons/ButtonSecondary/ButtonSecondary.module.scss
deleted file mode 100644
index 9eca6785..00000000
--- a/morpheus-client/components/buttons/ButtonSecondary/ButtonSecondary.module.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-@use "styles/colors";
-@use "styles/media";
-
-.buttonSecondary {
- cursor: pointer;
- box-sizing: border-box;
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
- padding: 16px;
- gap: 16px;
- width: 526px;
- height: 56px;
- background: colors.$background-secondary;
- border: 1px solid colors.$background-border;
- border-radius: 8px;
- flex: none;
- order: 0;
- flex-grow: 0;
-
- @include media.mobile {
- width: 100%;
- padding: 16px 0;
- }
-
- span {
- width: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 16px;
- }
-}
\ No newline at end of file
diff --git a/morpheus-client/components/buttons/ButtonSecondary/ButtonSecondary.tsx b/morpheus-client/components/buttons/ButtonSecondary/ButtonSecondary.tsx
deleted file mode 100644
index 9f2060c5..00000000
--- a/morpheus-client/components/buttons/ButtonSecondary/ButtonSecondary.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React, { CSSProperties } from "react";
-import Loader from "../../Loaders/LoaderCircle/Loader";
-import styles from "./ButtonSecondary.module.scss";
-
-interface ButtonSecondaryProps {
- loading: boolean;
- disabled?: boolean;
- text: string;
- onClick: (event?: any) => any;
- styles?: CSSProperties;
- className?: any;
- icon?: any;
-}
-
-const ButtonSecondary = (props: ButtonSecondaryProps) => {
- return (
-
- {props.loading ? (
-
- ) : (
-
- {props.icon && props.icon}
- {props.text}
-
- )}
-
- );
-};
-
-export default ButtonSecondary;
diff --git a/morpheus-client/context/AuthContext.tsx b/morpheus-client/context/AuthContext.tsx
index c89ba882..87f42089 100644
--- a/morpheus-client/context/AuthContext.tsx
+++ b/morpheus-client/context/AuthContext.tsx
@@ -51,7 +51,7 @@ const AuthContext = createContext
(defaultState);
const AuthProvider = (props: { children: ReactNode }) => {
const router = useRouter();
- const { showErrorAlert } = useToastContext();
+ const { showErrorAlert, showInfoAlert } = useToastContext();
const [authLoading, setAuthLoading] = useState(true);
const [authOption, setAuthOption] = useState(AuthOption.Login);
@@ -83,7 +83,7 @@ const AuthProvider = (props: { children: ReactNode }) => {
const registerWithEmailAndPassword = (user: UserRegistration): Promise => {
return signUpWithEmailAndPasswordFirebase(user)
.then((response) => {
- loadOrCreateMorpheusUser({ ...response, displayName: user.name });
+ loadOrCreateMorpheusUser({ ...response.user, displayName: user.name });
})
.catch((error) => {
showErrorAlert(error.message);
@@ -94,7 +94,7 @@ const AuthProvider = (props: { children: ReactNode }) => {
return new Promise((resolve, reject) => {
loginWithEmailAndPasswordFirebase(user)
.then((response: any) => {
- loadOrCreateMorpheusUser(response);
+ loadOrCreateMorpheusUser(response.user);
})
.catch((error) => {
showErrorAlert(error.message);
@@ -122,6 +122,7 @@ const AuthProvider = (props: { children: ReactNode }) => {
name: firebaseUser.displayName,
email: firebaseUser.email,
phone: firebaseUser.phoneNumber,
+ is_new_user: firebaseUser.isNewUser,
};
if (!user.email) {
showErrorAlert("Email is required");
@@ -136,7 +137,7 @@ const AuthProvider = (props: { children: ReactNode }) => {
if (response.success) {
setUser(response.data);
} else {
- showErrorAlert(response.error || "An error occurred while loading the user data");
+ showInfoAlert("Failed to load user data. Please try again later");
}
})
.catch(() => {
@@ -151,7 +152,7 @@ const AuthProvider = (props: { children: ReactNode }) => {
setUser(response.data);
setLocalUser(response.data);
} else {
- showErrorAlert("An error occurred while loading the user data");
+ showInfoAlert("Failed to load user data. Please try again later");
}
})
.catch(() => {
diff --git a/morpheus-client/excalidraw/components/SendToImagine/SendToImagine.tsx b/morpheus-client/excalidraw/components/SendToImagine/SendToImagine.tsx
index 0253dad4..a94cb84f 100644
--- a/morpheus-client/excalidraw/components/SendToImagine/SendToImagine.tsx
+++ b/morpheus-client/excalidraw/components/SendToImagine/SendToImagine.tsx
@@ -4,7 +4,7 @@ import { exportToBlob } from "../../packages/utils";
import { useImagine } from "@/context/ImagineContext";
import { getFileFromBlob } from "@/utils/images";
import { useApp, useExcalidrawAppState, useExcalidrawElements } from "../App";
-import ButtonPrimary from "@/components/buttons/ButtonPrimary/ButtonPrimary";
+import Button from "@/components/buttons/Button/Button";
import styles from "./SendToImagine.module.scss";
export const SendImageToImagine = () => {
@@ -35,8 +35,8 @@ export const SendImageToImagine = () => {
return (
-
-
+
{
createUserWithEmailAndPassword(auth, user.email, user.password)
.then((userCredential) => {
- resolve(userCredential.user);
+ resolve({
+ user: {
+ ...userCredential.user,
+ is_new_user: getAdditionalUserInfo(userCredential)?.isNewUser,
+ },
+ });
+
})
.catch((error) => {
reject(new Error(mapAuthCodeToMessage[error.code] || "Something went wrong with your sign up process"));
@@ -26,7 +32,12 @@ export const loginWithEmailAndPasswordFirebase = async (user: any): Promise
return new Promise((resolve, reject) => {
signInWithEmailAndPassword(auth, user.email, user.password)
.then((userCredential) => {
- resolve(userCredential.user);
+ resolve({
+ user: {
+ ...userCredential.user,
+ is_new_user: getAdditionalUserInfo(userCredential)?.isNewUser,
+ },
+ });
})
.catch((error) => {
reject(new Error(mapAuthCodeToMessage[error.code] || "Something went wrong with your authentication process"));
@@ -50,10 +61,14 @@ export const loginWithGoogleFirebase = async (): Promise => {
return new Promise((resolve, reject) => {
const provider = new GoogleAuthProvider();
signInWithPopup(auth, provider)
- .then((result) => {
- const user = result.user;
- const additionalInfo = getAdditionalUserInfo(result);
- resolve({ user, additionalInfo });
+ .then((userCredential) => {
+ resolve({
+ user: {
+ ...userCredential.user,
+ is_new_user: getAdditionalUserInfo(userCredential)?.isNewUser,
+ },
+ });
+
})
.catch((error) => {
reject(new Error(mapAuthCodeToMessage[error.code] || "Something went wrong with your authentication process"));
diff --git a/morpheus-client/services/users.ts b/morpheus-client/services/users.ts
index 1ef84785..7b1b9260 100644
--- a/morpheus-client/services/users.ts
+++ b/morpheus-client/services/users.ts
@@ -1,11 +1,12 @@
import axios from "./httpClient";
import { User } from "@/models/models";
import { signOutFirebase } from "./auth";
+import { clearStorageExceptCookies } from "@/utils/cookies";
export const logout = () => {
return signOutFirebase()
.then(() => {
- localStorage.clear();
+ clearStorageExceptCookies();
sessionStorage.clear();
setTimeout(() => {
window.location.href = "/";
diff --git a/morpheus-client/styles/_colors.scss b/morpheus-client/styles/_colors.scss
index 0edb161b..1c08ce82 100644
--- a/morpheus-client/styles/_colors.scss
+++ b/morpheus-client/styles/_colors.scss
@@ -23,6 +23,7 @@ $background-primary: #14172D;
$background-primary-2: #252238;
$background-primary-3: #312E47;
$background-primary-4: #6D6D94;
+$background-primary-5: #8B90B2;
$background-secondary: #252238;
$background-white: #FFFFFF;
$background-white-2: #F1F1F5;
diff --git a/morpheus-client/yarn.lock b/morpheus-client/yarn.lock
index 80c9f985..6d839623 100644
--- a/morpheus-client/yarn.lock
+++ b/morpheus-client/yarn.lock
@@ -543,11 +543,6 @@
resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.0.2.tgz"
integrity sha512-1zGIOkInkOLRv0QQGZ+3wffYsyKI4vIy62LYTvDWUn7TAYqnmXwougp9NSLqDeagLwgsv2URrykyAFixA/YqxA==
-"@next/swc-darwin-arm64@^13.4.19":
- version "13.4.19"
- resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz#77ad462b5ced4efdc26cb5a0053968d2c7dac1b6"
- integrity sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==
-
"@next/swc-darwin-x64@13.0.2":
version "13.0.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.0.2.tgz#d4a3fbe51edf871a675d89a7afdc78174d1e5841"
diff --git a/morpheus-server/app/migrations/versions/7592af049bd2_add_is_new_user_parameter.py b/morpheus-server/app/migrations/versions/7592af049bd2_add_is_new_user_parameter.py
new file mode 100644
index 00000000..811c92e8
--- /dev/null
+++ b/morpheus-server/app/migrations/versions/7592af049bd2_add_is_new_user_parameter.py
@@ -0,0 +1,26 @@
+"""add is_new_user parameter
+Revision ID: 7592af049bd2
+Revises: 27dddc20ef29
+Create Date: 2023-08-23 19:57:23.107454
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '7592af049bd2'
+down_revision = '27dddc20ef29'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column('user', sa.Column('is_new_user', sa.Boolean(), nullable=True))
+ # ### end Alembic commands ###
+
+
+def downgrade() -> None:
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_column('user', 'is_new_user')
+ # ### end Alembic commands ###
\ No newline at end of file
diff --git a/morpheus-server/app/models/models.py b/morpheus-server/app/models/models.py
index eb0c7c38..270c5976 100644
--- a/morpheus-server/app/models/models.py
+++ b/morpheus-server/app/models/models.py
@@ -15,6 +15,7 @@ class User(Base):
name = Column(String(64), nullable=True)
bio = Column(String(512), nullable=True)
avatar = Column(String(512), nullable=True)
+ is_new_user = Column(Boolean, default=True)
phone = Column(String(16), nullable=True)
is_active = Column(Boolean, default=True)
collections = relationship("Collection", back_populates="owner")
diff --git a/morpheus-server/app/models/schemas.py b/morpheus-server/app/models/schemas.py
index b25fdcba..2ba341b6 100644
--- a/morpheus-server/app/models/schemas.py
+++ b/morpheus-server/app/models/schemas.py
@@ -34,6 +34,7 @@ class User(BaseModel):
bio: str = None
avatar: str = None
phone: str = None
+ is_new_user: bool = True
class Config:
orm_mode = True
@@ -44,6 +45,7 @@ class Config:
"bio": "Juan Arias biography",
"avatar": "https://upload.wikimedia.org/wikipedia/en/8/86/Avatar_Aang.png", # noqa
"phone": "+573003000000",
+ "is_new_user": True,
}
}
diff --git a/morpheus-server/app/repository/user_repository.py b/morpheus-server/app/repository/user_repository.py
index afe53efb..7709eb00 100644
--- a/morpheus-server/app/repository/user_repository.py
+++ b/morpheus-server/app/repository/user_repository.py
@@ -38,6 +38,7 @@ def create_user(cls, *, db: Session, user: User) -> User:
email=user.email,
bio=user.bio,
avatar=f"https://ui-avatars.com/api/?name={avatar_seed}&background=random&size=128",
+ is_new_user=user.is_new_user,
)
db.add(db_user)
db.commit()
@@ -53,6 +54,7 @@ def update_user(cls, *, db: Session, user: User) -> Union[User, None]:
db_user.phone = user.phone
db_user.bio = user.bio
db_user.avatar = user.avatar
+ db_user.is_new_user = user.is_new_user
db.commit()
return db_user