diff --git a/front/app/orgs/[orgslug]/login/login.tsx b/front/app/orgs/[orgslug]/login/login.tsx new file mode 100644 index 00000000..d8f32cb8 --- /dev/null +++ b/front/app/orgs/[orgslug]/login/login.tsx @@ -0,0 +1,139 @@ +"use client"; +import learnhouseIcon from "public/learnhouse_bigicon_1.png"; +import FormLayout, { ButtonBlack, FormField, FormLabel, FormLabelAndMessage, FormMessage, Input } from '@components/StyledElements/Form/Form' +import Image from 'next/image'; +import * as Form from '@radix-ui/react-form'; +import { useFormik } from 'formik'; +import { getOrgLogoMediaDirectory } from "@services/media/media"; +import { BarLoader } from "react-spinners"; +import React from "react"; +import { loginAndGetToken } from "@services/auth/auth"; +import { AlertTriangle } from "lucide-react"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; +import { getUriWithOrg } from "@services/config/config"; + +interface LoginClientProps { + org: any; +} + +const validate = (values: any) => { + const errors: any = {}; + + if (!values.email) { + errors.email = 'Required'; + } + else if ( + !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email) + ) { + errors.email = 'Invalid email address'; + } + + if (!values.password) { + errors.password = 'Required'; + } + else if (values.password.length < 8) { + errors.password = 'Password must be at least 8 characters'; + } + + return errors; +}; + +const LoginClient = (props: LoginClientProps) => { + const [isSubmitting, setIsSubmitting] = React.useState(false); + const router = useRouter(); + const [error, setError] = React.useState(''); + const formik = useFormik({ + initialValues: { + email: '', + password: '', + }, + validate, + onSubmit: async values => { + setIsSubmitting(true); + let res = await loginAndGetToken(values.email, values.password); + let message = await res.json(); + if (res.status == 200) { + router.push(`/`); + setIsSubmitting(false); + } + else if (res.status == 401 || res.status == 400 || res.status == 404 || res.status == 409) { + setError(message.detail); + setIsSubmitting(false); + } + else { + setError("Something went wrong"); + setIsSubmitting(false); + } + + }, + }); + return ( +
+
+
+ + +
+
+
+
Login to
+
+ {props.org?.logo ? ( + Learnhouse + ) : ( + + )} +
+
{props.org?.name}
+
+
+
+
+
+ {error && ( +
+ +
{error}
+
+ )} + + + + + + + + {/* for password */} + + + + + + + + + +
+ + + +
+ +
+
+
+
+ ); +}; + +export default LoginClient + diff --git a/front/app/orgs/[orgslug]/login/page.tsx b/front/app/orgs/[orgslug]/login/page.tsx index 08aa23a7..11dd3f5b 100644 --- a/front/app/orgs/[orgslug]/login/page.tsx +++ b/front/app/orgs/[orgslug]/login/page.tsx @@ -1,110 +1,35 @@ -"use client"; -import { useRouter } from 'next/navigation'; -import React, { useState } from "react"; -import { styled } from '@stitches/react'; -import { loginAndGetToken } from "../../../../services/auth/auth"; -import FormLayout, { ButtonBlack, Flex, FormField, FormLabel, FormMessage, Input } from '@components/StyledElements/Form/Form'; -import * as Form from '@radix-ui/react-form'; -import { BarLoader } from 'react-spinners'; -import Toast from '@components/StyledElements/Toast/Toast'; -import { toast } from 'react-hot-toast'; +import { getOrganizationContextInfo } from "@services/organizations/orgs"; +import LoginClient from "./login"; +import { Metadata } from 'next'; -const Login = () => { - const [email, setEmail] = React.useState(""); - const [password, setPassword] = React.useState(""); - const [isSubmitting, setIsSubmitting] = useState(false); - const router = useRouter(); +type MetadataProps = { + params: { orgslug: string, courseid: string }; + searchParams: { [key: string]: string | string[] | undefined }; +}; - const handleSubmit = (e: any) => { - e.preventDefault(); - setIsSubmitting(true); - toast.promise( - loginAndGetToken(email, password), - { - loading: 'Logging in...', - success: () => { - router.push('/'); - return Logged in successfully; - }, - error: Wrong credentials, - } - ); +export async function generateMetadata( + { params }: MetadataProps, +): Promise { + const orgslug = params.orgslug; + // Get Org context information + const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); - setIsSubmitting(false); + return { + title: 'Login' + ` — ${org.name}`, }; +} - const handleEmailChange = (e: any) => { - setEmail(e.target.value); - }; - - const handlePasswordChange = (e: any) => { - setPassword(e.target.value); - }; +const Login = async (params: any) => { + const orgslug = params.params.orgslug; + const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); return (
- - - - - - - Email - Please provide an email - - - - - - - - Password - Please provide a password - - - - - - - - - - {isSubmitting ? : "Login"} - - - - - - - +
); }; -const LoginPage = styled('div', { - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - height: '100vh', - width: '100vw', - backgroundColor: '#f5f5f5', -}); -const LoginBox = styled('div', { - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - height: '40vh', - width: '40vw', - backgroundColor: '#ffffff', - borderRadius: 10, - - '@media (max-width: 768px)': { - width: '100vw', - height: '100vh', - borderRadius: 0, - }, -}); export default Login; diff --git a/front/app/orgs/[orgslug]/signup/page.tsx b/front/app/orgs/[orgslug]/signup/page.tsx index 29e13ff8..dd70b7f4 100644 --- a/front/app/orgs/[orgslug]/signup/page.tsx +++ b/front/app/orgs/[orgslug]/signup/page.tsx @@ -1,115 +1,33 @@ -"use client"; + import React from "react"; -import { signup } from "../../../../services/auth/auth"; -import { useRouter } from "next/navigation"; +import SignUpClient from "./signup"; +import { Metadata } from "next"; +import { getOrganizationContextInfo } from "@services/organizations/orgs"; -const SignUp = (params: any) => { - const org_slug = params.params.orgslug; - const router = useRouter(); - const [email, setEmail] = React.useState(""); - const [password, setPassword] = React.useState(""); - const [username, setUsername] = React.useState(""); +type MetadataProps = { + params: { orgslug: string, courseid: string }; + searchParams: { [key: string]: string | string[] | undefined }; +}; - const handleSubmit = (e: any) => { - e.preventDefault(); - console.log({ email, password, username, org_slug }); - alert(JSON.stringify({ email, password, username, org_slug })); - try { - signup({ email, password, username, org_slug }); - router.push("/"); - } - catch (err) { - console.log(err); - } +export async function generateMetadata( + { params }: MetadataProps, +): Promise { + const orgslug = params.orgslug; + // Get Org context information + const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); + + return { + title: 'Sign up' + ` — ${org.name}`, }; +} - const handleEmailChange = (e: any) => { - setEmail(e.target.value); - }; - - const handlePasswordChange = (e: any) => { - setPassword(e.target.value); - }; - - const handleUsernameChange = (e: any) => { - setUsername(e.target.value); - }; +const SignUp = async (params: any) => { + const orgslug = params.params.orgslug; + const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); return (
-
-
Sign up
- -
-
-
-
- - - - - - - - - - - - - - - Already have an account? Login - - - - Home - - - -
-
- -
-
-
+
); }; diff --git a/front/app/orgs/[orgslug]/signup/signup.tsx b/front/app/orgs/[orgslug]/signup/signup.tsx new file mode 100644 index 00000000..102af86c --- /dev/null +++ b/front/app/orgs/[orgslug]/signup/signup.tsx @@ -0,0 +1,188 @@ +"use client"; +import { useFormik } from 'formik'; +import { useRouter } from 'next/navigation'; +import learnhouseIcon from "public/learnhouse_bigicon_1.png"; +import React from 'react' +import FormLayout, { ButtonBlack, FormField, FormLabel, FormLabelAndMessage, FormMessage, Input, Textarea } from '@components/StyledElements/Form/Form' +import Image from 'next/image'; +import * as Form from '@radix-ui/react-form'; +import { getOrgLogoMediaDirectory } from '@services/media/media'; +import { AlertTriangle } from 'lucide-react'; +import Link from 'next/link'; +import { signup } from '@services/auth/auth'; +import { getUriWithOrg } from '@services/config/config'; + + +interface SignUpClientProps { + org: any; +} + +const validate = (values: any) => { + const errors: any = {}; + + if (!values.email) { + errors.email = 'Required'; + } + else if ( + !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email) + ) { + errors.email = 'Invalid email address'; + } + + if (!values.password) { + errors.password = 'Required'; + } + else if (values.password.length < 8) { + errors.password = 'Password must be at least 8 characters'; + } + + if (!values.username) { + errors.username = 'Required'; + } + + if (!values.username || values.username.length < 4) { + errors.username = 'Username must be at least 4 characters'; + } + + if (!values.full_name) { + errors.full_name = 'Required'; + } + + if (!values.bio) { + errors.bio = 'Required'; + } + + + return errors; +}; + + +function SignUpClient(props: SignUpClientProps) { + const [isSubmitting, setIsSubmitting] = React.useState(false); + const router = useRouter(); + const [error, setError] = React.useState(''); + const formik = useFormik({ + initialValues: { + org_slug: props.org?.slug, + email: '', + password: '', + username: '', + bio: '', + full_name: '', + }, + validate, + onSubmit: async values => { + setIsSubmitting(true); + let res = await signup(values); + let message = await res.json(); + if (res.status == 200) { + router.push(`/`); + setIsSubmitting(false); + } + else if (res.status == 401 || res.status == 400 || res.status == 404 || res.status == 409) { + setError(message.detail); + setIsSubmitting(false); + } + else { + setError("Something went wrong"); + setIsSubmitting(false); + } + + }, + }); + + return ( +
+
+
+ + + +
+
+
+
Join
+
+ {props.org?.logo ? ( + Learnhouse + ) : ( + + )} +
+
{props.org?.name}
+
+
+
+
+
+ {error && ( +
+ +
{error}
+
+ )} + + + + + + + + {/* for password */} + + + + + + + + {/* for username */} + + + + + + + + + {/* for full name */} + + + + + + + + + + {/* for bio */} + + + + +