Skip to content

Commit

Permalink
feat:init hostels page
Browse files Browse the repository at this point in the history
  • Loading branch information
heydoyouknowme0 committed Sep 1, 2024
1 parent ed9fb2a commit 9ab7d5c
Show file tree
Hide file tree
Showing 7 changed files with 420 additions and 2 deletions.
174 changes: 174 additions & 0 deletions app/[locale]/hostels/[url_name]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import Link from 'next/link';
import { Fragment } from 'react';
import { notFound } from 'next/navigation';

import Heading from '~/components/heading';
import ImageHeader from '~/components/image-header';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '~/components/ui';
import { getTranslations, type Translations } from '~/i18n/translations';
import { db } from '~/server/db';

export default async function Hostel({
params: { locale, url_name },
}: {
params: {
locale: string;
url_name: string;
};
}) {
const hostel = await db.query.hostels.findFirst({
where: (hostels, { eq }) => eq(hostels.urlName, url_name),
columns: {
address: true,
name: true,
telephone: true,
type: true,
alternateTelephone: true,
email: true,
overview: true,
staffOverview: true,
facilities: true,
},
with: {
hostelFaculty: {
columns: {
post: true,
},
with: {
faculty: {
columns: {
designation: true,
},
with: {
person: {
columns: {
name: true,
telephone: true,
email: true,
},
},
},
},
},
},
hostelStaff: {
columns: {
post: true,
},
with: {
staff: {
columns: {
designation: true,
},
with: {
person: {
columns: {
name: true,
telephone: true,
email: true,
},
},
},
},
},
},
},
});

if (!hostel) {
return notFound();
}

const text = (await getTranslations(locale)).Hostels.hostelDetails;

return (
<>
<ImageHeader title={hostel.name} src={`hostels/${url_name}/logo.png`} />
<section className="container">
<h5>
<b className="text-primary-700">{text.contact}</b>
{hostel.telephone}
{hostel.alternateTelephone && ', ' + hostel.alternateTelephone}
</h5>
<h5>
<b className="text-primary-700">{text.email}</b>
<Link href={`mailto:${hostel.email}`}>{hostel.email}</Link>
</h5>
<iframe
className="aspect-video min-w-[50%] max-lg:w-full"
src={`https://www.google.com/maps/embed?pb=${hostel.address}`}
allowFullScreen={true}
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
/>
<br />

<h4>{text.overview}</h4>
<ul className="list-inside list-disc">
{hostel.overview?.map((paragraph, i) => <li key={i}>{paragraph}</li>)}
</ul>
<h4>{text.staffOverview}</h4>
<ul className="list-inside list-disc">
{hostel.staffOverview.map((paragraph, i) => (
<li key={i}>{paragraph}</li>
))}
</ul>
<h4>{text.facilities}</h4>
<ul className="list-inside list-disc">
{hostel.facilities.map((paragraph, i) => (
<li key={i}>{paragraph}</li>
))}
</ul>
</section>
<Heading
heading="h3"
text={text.staff}
glyphDirection="rtl"
href="#staff"
className="container"
/>
<section className="container">
{[hostel.hostelFaculty, hostel.hostelStaff].map((staff, index) => (
<Fragment key={index}>
<h4 className="mt-10">
{index === 0 ? text.faculty : `${text.general} ${text.staff}`}
</h4>
<Table>
<TableHeader>
<TableRow>
<TableHead>{text.hostelsStaffTable.name}</TableHead>
<TableHead>{text.hostelsStaffTable.designation}</TableHead>
<TableHead>{text.hostelsStaffTable.hostelPost}</TableHead>
<TableHead>{text.contact}</TableHead>
<TableHead>{text.email}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{hostel.hostelStaff.map(({ post, staff }) => (
<TableRow key={staff.person.email}>
<TableCell>{staff.person.name}</TableCell>
<TableCell>{staff.designation}</TableCell>
<TableCell>{post}</TableCell>
<TableCell>{staff.person.telephone}</TableCell>
<TableCell>
<Link href={`mailto:${staff.person.email}`}>
{staff.person.email}
</Link>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Fragment>
))}
</section>
</>
);
}
163 changes: 163 additions & 0 deletions app/[locale]/hostels/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
'use server';
import Link from 'next/link';
import { Suspense } from 'react';
import Image from 'next/image';
import { MdBadge } from 'react-icons/md';

import { cn, groupBy } from '~/lib/utils';
import { getS3Url } from '~/server/s3';
import Heading from '~/components/heading';
import ImageHeader from '~/components/image-header';
import { getTranslations } from '~/i18n/translations';
import { Card, CardDescription, ScrollArea } from '~/components/ui';
import { db } from '~/server/db';
import { Button } from '~/components/buttons';
import Loading from '~/components/loading';

import { NotificationsList } from '../notifications';

export default async function Hostels({
params: { locale },
}: {
params: { locale: string };
}) {
const text = (await getTranslations(locale)).Hostels;
const hostels = await db.query.hostels.findMany({
columns: { name: true, urlName: true, type: true },
});
const groupedHostels = groupBy(hostels, 'type') as Map<
'boys' | 'girls',
typeof hostels
>;

return (
<>
<ImageHeader title="Hostels" src="assets/hostels.jpg" />
<HostelList
hostelType="boys"
hostels={groupedHostels.get('boys')!}
locale={locale}
text={text.boysHostels}
/>
<HostelList
hostelType="girls"
hostels={groupedHostels.get('girls')!}
locale={locale}
text={text.girlsHostels}
/>
<section id="notification" className="container">
<Heading
text={text.notificationsTitle}
heading="h3"
href="#notification"
glyphDirection={'rtl'}
/>
<section
className={cn(
`h-[384px] rounded-xl rounded-b-xl bg-background/[0.6] md:h-[512px]`,
'lg:rounded-t-xl lg:shadow-[0px_8px_0px_#e13f32_inset,_-12px_22px_60px_rgba(0,_43,_91,_0.15)] lg:drop-shadow-2xl',
'lg:px-6 lg:py-8 xl:px-8'
)}
>
<ScrollArea
type="always"
className={cn(
'h-full',
'px-3 py-3 md:px-5 md:py-5 lg:py-5 lg:pl-0 lg:pr-4 xl:pr-6'
)}
>
<ol className="space-y-2 sm:space-y-4 md:space-y-6">
<Suspense fallback={<Loading />} key={'hostel'}>
<NotificationsList category="hostel" locale={locale} />
</Suspense>
</ol>
</ScrollArea>
</section>
</section>
<section id="rules-and-conducts" className="container">
<Heading
text={text.misc}
heading="h3"
href="#rules-and-conducts"
glyphDirection={'ltr'}
/>
<nav
className={cn(
'container',
'my-10 md:my-12 lg:my-16 xl:my-20',
'flex flex-col gap-5 lg:flex-row lg:justify-around'
)}
>
<Button
asChild
className={cn(
'flex flex-col',
'gap-2 md:gap-3 lg:gap-4 xl:gap-5',
'h-40 md:h-48 lg:h-60 lg:w-72 xl:w-80 2xl:w-96'
)}
variant="secondary"
>
<Link href={getS3Url() + '/hostels/rules.pdf'} target="_blank">
<MdBadge className="size-12" />
<p className="font-serif font-semibold sm:text-lg md:text-xl">
{text.rulesTitle}
</p>
</Link>
</Button>
</nav>
</section>
</>
);
}
const HostelList = ({
hostelType,
hostels,
locale,
text,
}: {
hostelType: 'boys' | 'girls';
hostels: { name: string; urlName: string; type: string }[];
locale: string;
text: string;
}) => {
return (
<section id={`${hostelType}-hostel`} className="container">
<Heading
text={text}
heading="h3"
href={`#${hostelType}-hostel`}
glyphDirection={'ltr'}
/>
<ol
className={cn(
'flex flex-row flex-wrap justify-start',
'gap-6 sm:gap-7 md:gap-8 lg:gap-9 xl:gap-10'
)}
>
{hostels.map(({ name, urlName }, index) => (
<Link href={`/${locale}/hostels/${urlName}`} key={index}>
<Card
className={cn(
'flex flex-col items-center justify-center',
'drop-shadow hover:drop-shadow-lg',
'p-4 sm:p-5 md:p-6 lg:p-7 xl:p-8',
'size-48 sm:size-56 md:size-64'
)}
>
<CardDescription className="grow">
<Image
alt={name}
className="size-full scale-50 rounded-full object-cover"
src={`hostels/${urlName}/logo.png`}
width={0}
height={0}
/>
</CardDescription>
<h5>{name}</h5>
</Card>
</Link>
))}
</ol>
</section>
);
};
2 changes: 1 addition & 1 deletion app/[locale]/notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default async function Notifications({
);
}

const NotificationsList = async ({
export const NotificationsList = async ({
category,
locale,
}: {
Expand Down
27 changes: 27 additions & 0 deletions i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,33 @@ const text: Translations = {
login: 'Login',
profile: { alt: 'Profile image', view: 'View Profile' },
},
Hostels: {
title: 'Hostels',
notificationsTitle: 'Hostel Notifications',
boysHostels: 'Boys Hostels',
girlsHostels: 'Girls Hostels',
misc: 'Miscellaneous',
rulesTitle: 'Hostel Rules & Conducts',
hostelDetails: {
name: 'Hostel Name: ',
overview: 'Hostel Overview',
staffOverview: 'Hostel Staff Overview',
facilities: 'Hostel Facilities Overview',
contact: 'Contact us: ',
email: 'Email: ',
wardens: 'Wardens: ',
faculty: 'Faculty',
staff: 'Staff',
general: 'General',
hostelsStaffTable: {
name: 'Name',
designation: 'Designation',
contact: 'Contact',
hostelPost: 'Hostel Post',
email: 'Email',
},
},
},
Login: {
title: 'Sign In',
enterEmail: 'Enter your email',
Expand Down
Loading

0 comments on commit 9ab7d5c

Please sign in to comment.