Skip to content

Commit

Permalink
sign up process (#59)
Browse files Browse the repository at this point in the history
* sign up process

* finalize sign up process

* fix lint
  • Loading branch information
mahmoudmoravej authored Feb 29, 2024
1 parent 895335e commit 6cc5c19
Show file tree
Hide file tree
Showing 17 changed files with 475 additions and 93 deletions.
79 changes: 78 additions & 1 deletion app/@types/graphql/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ export type Mutation = {
reportCreate?: Maybe<ReportCreatePayload>;
/** Updates a report by id */
reportUpdate?: Maybe<ReportUpdatePayload>;
/** Sign up to an organization */
signUp?: Maybe<SignUpPayload>;
/** Creates a new vision */
visionCreate?: Maybe<VisionCreatePayload>;
/** Update an existing vision by id */
Expand Down Expand Up @@ -559,6 +561,11 @@ export type MutationReportUpdateArgs = {
};


export type MutationSignUpArgs = {
input: SignUpInput;
};


export type MutationVisionCreateArgs = {
input: VisionCreateInput;
};
Expand Down Expand Up @@ -788,6 +795,26 @@ export type ReportUpdatePayload = {
report: Report;
};

/** Autogenerated input type of SignUp */
export type SignUpInput = {
/** A unique identifier for the client performing the mutation. */
clientMutationId?: InputMaybe<Scalars['String']['input']>;
signUpInput: SignUpInputs;
};

export type SignUpInputs = {
organizationId?: InputMaybe<Scalars['Int']['input']>;
};

/** Autogenerated return type of SignUp. */
export type SignUpPayload = {
__typename?: 'SignUpPayload';
/** A unique identifier for the client performing the mutation. */
clientMutationId?: Maybe<Scalars['String']['output']>;
/** Returns signed up user info */
result: UserInfo;
};

export type UserInfo = {
__typename?: 'UserInfo';
Individual?: Maybe<Individual>;
Expand Down Expand Up @@ -1108,6 +1135,13 @@ export type GetLoggedInUserInfoQueryVariables = Exact<{ [key: string]: never; }>

export type GetLoggedInUserInfoQuery = { __typename?: 'Query', myInfo: { __typename?: 'UserInfo', UserId: number, Individual?: { __typename?: 'Individual', id: number, isManager: boolean, organizationId: number } | null, Organization?: { __typename?: 'Organization', isPersonal: boolean } | null } };

export type SignUpMutationVariables = Exact<{
input: SignUpInput;
}>;


export type SignUpMutation = { __typename?: 'Mutation', signUp?: { __typename?: 'SignUpPayload', result: { __typename?: 'UserInfo', UserId: number, Individual?: { __typename?: 'Individual', id: number, isManager: boolean, organizationId: number } | null, Organization?: { __typename?: 'Organization', isPersonal: boolean } | null } } | null };

export const ActivityFragmentFragmentDoc = gql`
fragment ActivityFragment on Activity {
id
Expand Down Expand Up @@ -2220,4 +2254,47 @@ export function useGetLoggedInUserInfoSuspenseQuery(baseOptions?: Apollo.Suspens
export type GetLoggedInUserInfoQueryHookResult = ReturnType<typeof useGetLoggedInUserInfoQuery>;
export type GetLoggedInUserInfoLazyQueryHookResult = ReturnType<typeof useGetLoggedInUserInfoLazyQuery>;
export type GetLoggedInUserInfoSuspenseQueryHookResult = ReturnType<typeof useGetLoggedInUserInfoSuspenseQuery>;
export type GetLoggedInUserInfoQueryResult = Apollo.QueryResult<GetLoggedInUserInfoQuery, GetLoggedInUserInfoQueryVariables>;
export type GetLoggedInUserInfoQueryResult = Apollo.QueryResult<GetLoggedInUserInfoQuery, GetLoggedInUserInfoQueryVariables>;
export const SignUpDocument = gql`
mutation signUp($input: SignUpInput!) {
signUp(input: $input) {
result {
UserId
Individual {
id
isManager
organizationId
}
Organization {
isPersonal
}
}
}
}
`;
export type SignUpMutationFn = Apollo.MutationFunction<SignUpMutation, SignUpMutationVariables>;

/**
* __useSignUpMutation__
*
* To run a mutation, you first call `useSignUpMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useSignUpMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [signUpMutation, { data, loading, error }] = useSignUpMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useSignUpMutation(baseOptions?: Apollo.MutationHookOptions<SignUpMutation, SignUpMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<SignUpMutation, SignUpMutationVariables>(SignUpDocument, options);
}
export type SignUpMutationHookResult = ReturnType<typeof useSignUpMutation>;
export type SignUpMutationResult = Apollo.MutationResult<SignUpMutation>;
export type SignUpMutationOptions = Apollo.BaseMutationOptions<SignUpMutation, SignUpMutationVariables>;
2 changes: 1 addition & 1 deletion app/contexts/apollo/apolloClientProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const ApolloClientProvider = ({
return getApolloClient(
sessionStorage.getItem("graphql_url"),
user?.jwt_token,
user?.organization_id?.toString(),
{ organization_id: user?.organization_id?.toString() },
window.__APOLLO_STATE__,
);
}, [user?.jwt_token, user?.organization_id]);
Expand Down
2 changes: 1 addition & 1 deletion app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ function buildApolloClient(user: User | null) {
return utils.getApolloClient(
process.env.GRAPHQL_SCHEMA_URL,
user?.jwt_token,
user?.organization_id.toString(),
{ organization_id: user?.organization_id.toString() },
);
}

Expand Down
157 changes: 157 additions & 0 deletions app/routes/_auth.signin.($id).tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { Form, useLoaderData } from "@remix-run/react";
import { Alert, Button, Typography } from "@material-tailwind/react";
import { Link } from "react-router-dom";

import { LoaderFunctionArgs, json } from "@remix-run/node";
import cookie from "cookie";
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";

export function loader({ params, request }: LoaderFunctionArgs) {
const organization_id = params.id;

const cookieString = request.headers.get("cookie") ?? "";
const signinError = cookie.parse(cookieString)["signin-error"];

return json(
{
error: signinError,
},
{
headers: [
["Set-Cookie", setClearErrorCookie()],
["Set-Cookie", getAuthenticationOrganizationCookie(organization_id)],
],
},
);
}
function setClearErrorCookie(): string {
return "signin-error=; Path=/; Max-Age=0";
}

function getAuthenticationOrganizationCookie(organization_id?: string): string {
// TODO: we later remove this as we get the org by subdomain or even the email addrees
return `auth_organization_id=${organization_id}; Path=/; ${
organization_id ? "" : "Max-Age=0"
}`;
}

export default function SignIn() {
const { error: errorPresent } = useLoaderData<typeof loader>();

const errorMarkup = true && (
<Alert
color="amber"
icon={<ExclamationTriangleIcon className="h-5 w-5 text-inherit" />}
>
You are not authorized! You have to{" "}
<Link to="/signup" className="hover:underline">
sign up
</Link>{" "}
first.
</Alert>
);

return (
<>
<section className="m-8 flex gap-4">
<div className="mt-24 w-full lg:w-3/5">
<div className="text-center">
<Typography variant="h2" className="mb-4 font-bold">
Sign In
</Typography>

<Typography
variant="paragraph"
color="blue-gray"
className="text-lg font-normal"
>
Choose one to sign in.
</Typography>
</div>
<div className="mx-auto mb-2 mt-8 w-80 max-w-screen-lg lg:w-1/2">
<div className="mt-8 space-y-4">
{errorPresent && errorMarkup}
<Form action={`/auth/google/signin`} method="post">
<Button
size="lg"
color="white"
className="flex items-center justify-center gap-2 shadow-md"
fullWidth
type="submit"
>
<svg
width="17"
height="16"
viewBox="0 0 17 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_1156_824)">
<path
d="M16.3442 8.18429C16.3442 7.64047 16.3001 7.09371 16.206 6.55872H8.66016V9.63937H12.9813C12.802 10.6329 12.2258 11.5119 11.3822 12.0704V14.0693H13.9602C15.4741 12.6759 16.3442 10.6182 16.3442 8.18429Z"
fill="#4285F4"
/>
<path
d="M8.65974 16.0006C10.8174 16.0006 12.637 15.2922 13.9627 14.0693L11.3847 12.0704C10.6675 12.5584 9.7415 12.8347 8.66268 12.8347C6.5756 12.8347 4.80598 11.4266 4.17104 9.53357H1.51074V11.5942C2.86882 14.2956 5.63494 16.0006 8.65974 16.0006Z"
fill="#34A853"
/>
<path
d="M4.16852 9.53356C3.83341 8.53999 3.83341 7.46411 4.16852 6.47054V4.40991H1.51116C0.376489 6.67043 0.376489 9.33367 1.51116 11.5942L4.16852 9.53356Z"
fill="#FBBC04"
/>
<path
d="M8.65974 3.16644C9.80029 3.1488 10.9026 3.57798 11.7286 4.36578L14.0127 2.08174C12.5664 0.72367 10.6469 -0.0229773 8.65974 0.000539111C5.63494 0.000539111 2.86882 1.70548 1.51074 4.40987L4.1681 6.4705C4.8001 4.57449 6.57266 3.16644 8.65974 3.16644Z"
fill="#EA4335"
/>
</g>
<defs>
<clipPath id="clip0_1156_824">
<rect
width="16"
height="16"
fill="white"
transform="translate(0.5)"
/>
</clipPath>
</defs>
</svg>
<span>Sign in With Google</span>
</Button>
</Form>
<Button
size="lg"
color="white"
className="flex items-center justify-center gap-2 shadow-md"
fullWidth
>
<img
src="/images/twitter-logo.svg"
height={24}
width={24}
alt=""
/>
<span>Sign in With Twitter</span>
</Button>
</div>
<Typography
variant="paragraph"
className="mt-4 text-center font-medium text-blue-gray-500"
>
Not registered?
<Link to="/signup" className="ml-1 text-gray-900">
Create account
</Link>
</Typography>
</div>
</div>
<div className="hidden h-full w-2/5 lg:block">
<img
src="/images/pattern.png"
className="h-full w-full rounded-3xl object-cover"
alt=""
/>
</div>
</section>
</>
);
}
Loading

0 comments on commit 6cc5c19

Please sign in to comment.