Skip to content

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tomas-salgado committed Jul 20, 2024
1 parent cb3e329 commit 8787bc8
Show file tree
Hide file tree
Showing 15 changed files with 840 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
type ActionFunctionArgs,
json,
type LoaderFunctionArgs,
redirect,
} from '@remix-run/node';
import { useActionData, useSearchParams } from '@remix-run/react';

import { AddInterviewReviewInput } from '@oyster/core/employment';
import { addInterviewReview } from '@oyster/core/employment.server';
import { getErrors, Modal, validateForm } from '@oyster/ui';

import { AddInterviewReviewForm } from '@/shared/components/interview-review-form';
import { Route } from '@/shared/constants';
import {
commitSession,
ensureUserAuthenticated,
toast,
user,
} from '@/shared/session.server';

export async function loader({ request }: LoaderFunctionArgs) {
await ensureUserAuthenticated(request);

return json({});
}

export async function action({ request }: ActionFunctionArgs) {
const session = await ensureUserAuthenticated(request);

const form = await request.formData();

form.set('studentId', user(session));

const { data, errors, ok } = await validateForm(
form,
AddInterviewReviewInput
);

if (!ok) {
return json({ errors }, { status: 400 });
}

await addInterviewReview({
companyId: data.companyId,
interviewPosition: data.interviewPosition,
text: data.text,
studentId: data.studentId,
});

toast(session, {
message: 'Your review has been added! 🎉',
});

return redirect(Route['/companies'], {
headers: {
'Set-Cookie': await commitSession(session),
},
});
}

export default function AddInterviewReviewModal() {
const { error, errors } = getErrors(useActionData<typeof action>());
const [searchParams] = useSearchParams();

return (
<Modal
onCloseTo={{
pathname: Route['/companies'],
search: searchParams.toString(),
}}
>
<Modal.Header>
<Modal.Title>Add Interview Review</Modal.Title>
<Modal.CloseButton />
</Modal.Header>

<AddInterviewReviewForm error={error} errors={errors} />
</Modal>
);
}

//integrate crunchbase?? to be able to search for a field and add company
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
type ActionFunctionArgs,
json,
type LoaderFunctionArgs,
redirect,
} from '@remix-run/node';
import { useActionData, useLoaderData } from '@remix-run/react';

import { EditInterviewReviewInput } from '@oyster/core/employment';
import {
editInterviewReview,
getInterviewReview,
} from '@oyster/core/employment.server';
import { getErrors, Modal, validateForm } from '@oyster/ui';

import { EditInterviewReviewForm } from '@/shared/components/interview-review-form';
import { Route } from '@/shared/constants';
import {
commitSession,
ensureUserAuthenticated,
toast,
} from '@/shared/session.server';

export async function loader({ params, request }: LoaderFunctionArgs) {
await ensureUserAuthenticated(request);

const review = await getInterviewReview({
where: { interviewReviewId: params.id as string },
});

if (!review) {
throw new Response(null, { status: 404 });
}

return json({
review,
});
}

export async function action({ params, request }: ActionFunctionArgs) {
const session = await ensureUserAuthenticated(request);

const form = await request.formData();

form.set('interviewReviewId', params.id as string);

const { data, errors, ok } = await validateForm(
form,
EditInterviewReviewInput
);

if (!ok) {
return json({ errors }, { status: 400 });
}

await editInterviewReview({
interviewPosition: data.interviewPosition,
text: data.text,
interviewReviewId: params.interviewReviewId as string,
companyId: '0n08gflgpkqz', // TODO: fix company id submission
});

toast(session, {
message: 'Your review has been updated!',
});

return redirect(Route['/profile/work'], {
headers: {
'Set-Cookie': await commitSession(session),
},
});
}

export default function EditReviewModal() {
const { error, errors } = getErrors(useActionData<typeof action>());
const { review } = useLoaderData<typeof loader>();

return (
<Modal onCloseTo={Route['/companies']}>
<Modal.Header>
<Modal.Title>Edit Interview Review</Modal.Title>
<Modal.CloseButton />
</Modal.Header>

<EditInterviewReviewForm error={error} errors={errors} review={review} />
</Modal>
);
}
2 changes: 1 addition & 1 deletion apps/member-profile/app/routes/_profile.companies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function AddReviewLink() {
<Link
className={getButtonCn({})}
to={{
pathname: Route['/companies/reviews/add'],
pathname: Route['/companies/interview-reviews/add'], //for testing
search: searchParams.toString(),
}}
>
Expand Down
117 changes: 106 additions & 11 deletions apps/member-profile/app/routes/_profile.companies_.$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
import { generatePath, Link, useLoaderData } from '@remix-run/react';
import dayjs from 'dayjs';
import { ExternalLink } from 'react-feather';
import { useSearchParams } from 'react-router-dom';

import {
type EmploymentType,
Expand All @@ -15,6 +16,7 @@ import {
getCompany,
listCompanyEmployees,
listCompanyReviews,
listInterviewReviews,
} from '@oyster/core/employment.server';
import { cx, Divider, getTextCn, ProfilePicture, Text } from '@oyster/ui';
import {
Expand All @@ -26,6 +28,8 @@ import {

import { Card } from '@/shared/components/card';
import { CompanyReview } from '@/shared/components/company-review';
import { InterviewReview } from '@/shared/components/interview-review';
import { NavigationItem } from '@/shared/components/navigation';
import { Route } from '@/shared/constants';
import { ensureUserAuthenticated, user } from '@/shared/session.server';

Expand All @@ -34,7 +38,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) {

const id = params.id as string;

const [company, _employees, _reviews] = await Promise.all([
const [company, _employees, _reviews, _interviewReviews] = await Promise.all([
getCompany({
include: ['averageRating', 'employees', 'reviews'],
select: [
Expand Down Expand Up @@ -74,6 +78,20 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
],
where: { companyId: id },
}),

listInterviewReviews({
select: [
'interviewReviews.createdAt',
'interviewReviews.id',
'interviewReviews.text',
'interviewReviews.interviewPosition as title',
'students.id as reviewerId',
'students.firstName as reviewerFirstName',
'students.lastName as reviewerLastName',
'students.profilePicture as reviewerProfilePicture',
],
where: { companyId: id },
}),
]);

if (!company) {
Expand Down Expand Up @@ -117,16 +135,26 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
}
);

const interviewReviews = _interviewReviews.map(({ createdAt, ...review }) => {
return {
...review,
reviewedAt: dayjs().to(createdAt),
};
});

return json({
company,
currentEmployees,
pastEmployees,
reviews,
interviewReviews,
});
}

export default function CompanyPage() {
const { company } = useLoaderData<typeof loader>();
const [searchParams] = useSearchParams();
const activeTab = searchParams.get('tab') || 'employees';

return (
<section className="mx-auto flex w-full max-w-[36rem] flex-col gap-[inherit]">
Expand Down Expand Up @@ -156,9 +184,23 @@ export default function CompanyPage() {
</header>

<Text color="gray-500">{company.description}</Text>
<ReviewsList />
<CurrentEmployees />
<PastEmployees />
<nav>
<ul className="flex flex-wrap gap-x-4 gap-y-2">
<NavigationItem to="?tab=employees">Employees</NavigationItem>
<NavigationItem to="?tab=reviews">Company Reviews</NavigationItem>
<NavigationItem to="?tab=interview-reviews">
Interview Reviews
</NavigationItem>
</ul>
</nav>
<Divider my="4" />
{activeTab === 'employees' && (
<>
<Employees />
</>
)}
{activeTab === 'reviews' && <ReviewsList />}
{activeTab === 'interview-reviews' && <InterviewReviewsList />}
</section>
);
}
Expand Down Expand Up @@ -236,7 +278,7 @@ function ReviewsList() {
<>
<section className="flex flex-col gap-[inherit]">
<Text weight="500" variant="lg">
Reviews ({reviews.length})
Company Reviews ({reviews.length})
</Text>

<CompanyReview.List>
Expand Down Expand Up @@ -270,15 +312,70 @@ function ReviewsList() {
})}
</CompanyReview.List>
</section>
</>
);
}

<Divider my="4" />
function InterviewReviewsList() {
const { interviewReviews } = useLoaderData<typeof loader>();

if (!interviewReviews.length) {
return null;
}

return (
<>
<section className="flex flex-col gap-[inherit]">
<Text weight="500" variant="lg">
Interview Reviews ({interviewReviews.length})
</Text>

<InterviewReview.List>
{interviewReviews.map((interviewReview) => {
return (
<InterviewReview
interviewReviewId={interviewReview.id}
key={interviewReview.id}
company={{
id: interviewReview.companyId || '',
image: interviewReview.companyImage || '',
name: interviewReview.companyName || '',
}}
reviewedAt={interviewReview.reviewedAt}
reviewerFirstName={interviewReview.reviewerFirstName || ''}
reviewerId={interviewReview.reviewerId || ''}
reviewerLastName={interviewReview.reviewerLastName || ''}
reviewerProfilePicture={interviewReview.reviewerProfilePicture}
text={interviewReview.text}
title={interviewReview.title || ''}
/>
);
})}
</InterviewReview.List>
</section>
</>
);
}

function CurrentEmployees() {
const { currentEmployees } = useLoaderData<typeof loader>();
function Employees() {
const { currentEmployees, pastEmployees } = useLoaderData<typeof loader>();

return (
<>
<Text weight="500" variant="lg">
Employees ({currentEmployees.length + pastEmployees.length})
</Text>
<CurrentEmployees currentEmployees={currentEmployees} />
<PastEmployees pastEmployees={pastEmployees} />
</>
);
}

function CurrentEmployees({
currentEmployees,
}: {
currentEmployees: EmployeeInView[];
}) {
return (
<Card>
<Card.Title>Current Employees ({currentEmployees.length})</Card.Title>
Expand All @@ -298,9 +395,7 @@ function CurrentEmployees() {
);
}

function PastEmployees() {
const { pastEmployees } = useLoaderData<typeof loader>();

function PastEmployees({ pastEmployees }: { pastEmployees: EmployeeInView[] }) {
return (
<Card>
<Card.Title>Past Employees ({pastEmployees.length})</Card.Title>
Expand Down
Loading

0 comments on commit 8787bc8

Please sign in to comment.