diff --git a/app/[locale]/hostels/[url_name]/page.tsx b/app/[locale]/hostels/[url_name]/page.tsx
new file mode 100644
index 00000000..ee833e34
--- /dev/null
+++ b/app/[locale]/hostels/[url_name]/page.tsx
@@ -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 (
+ <>
+
+
+
+ {text.contact}
+ {hostel.telephone}
+ {hostel.alternateTelephone && ', ' + hostel.alternateTelephone}
+
+
+ {text.email}
+ {hostel.email}
+
+
+
+
+ {text.overview}
+
+ {hostel.overview?.map((paragraph, i) => - {paragraph}
)}
+
+ {text.staffOverview}
+
+ {hostel.staffOverview.map((paragraph, i) => (
+ - {paragraph}
+ ))}
+
+ {text.facilities}
+
+ {hostel.facilities.map((paragraph, i) => (
+ - {paragraph}
+ ))}
+
+
+
+
+ {[hostel.hostelFaculty, hostel.hostelStaff].map((staff, index) => (
+
+
+ {index === 0 ? text.faculty : `${text.general} ${text.staff}`}
+
+
+
+
+ {text.hostelsStaffTable.name}
+ {text.hostelsStaffTable.designation}
+ {text.hostelsStaffTable.hostelPost}
+ {text.contact}
+ {text.email}
+
+
+
+ {hostel.hostelStaff.map(({ post, staff }) => (
+
+ {staff.person.name}
+ {staff.designation}
+ {post}
+ {staff.person.telephone}
+
+
+ {staff.person.email}
+
+
+
+ ))}
+
+
+
+ ))}
+
+ >
+ );
+}
diff --git a/app/[locale]/hostels/page.tsx b/app/[locale]/hostels/page.tsx
new file mode 100644
index 00000000..4724b79d
--- /dev/null
+++ b/app/[locale]/hostels/page.tsx
@@ -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 (
+ <>
+
+
+
+
+
+
+
+
+ } key={'hostel'}>
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+const HostelList = ({
+ hostelType,
+ hostels,
+ locale,
+ text,
+}: {
+ hostelType: 'boys' | 'girls';
+ hostels: { name: string; urlName: string; type: string }[];
+ locale: string;
+ text: string;
+}) => {
+ return (
+
+
+
+ {hostels.map(({ name, urlName }, index) => (
+
+
+
+
+
+ {name}
+
+
+ ))}
+
+
+ );
+};
diff --git a/app/[locale]/notifications.tsx b/app/[locale]/notifications.tsx
index e0c77b13..b137491f 100644
--- a/app/[locale]/notifications.tsx
+++ b/app/[locale]/notifications.tsx
@@ -105,7 +105,7 @@ export default async function Notifications({
);
}
-const NotificationsList = async ({
+export const NotificationsList = async ({
category,
locale,
}: {
diff --git a/i18n/en.ts b/i18n/en.ts
index 481e525d..a995152a 100644
--- a/i18n/en.ts
+++ b/i18n/en.ts
@@ -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',
diff --git a/i18n/hi.ts b/i18n/hi.ts
index 8af092bd..7ad5cd43 100644
--- a/i18n/hi.ts
+++ b/i18n/hi.ts
@@ -98,6 +98,33 @@ const text: Translations = {
login: 'प्रवेश',
profile: { alt: 'मेरी छवि', view: 'विवरण देखें' },
},
+ Hostels: {
+ title: 'छात्रावास',
+ notificationsTitle: 'छात्रावास सूचनाएँ',
+ boysHostels: 'लड़कों के छात्रावास',
+ girlsHostels: 'लड़कियों के छात्रावास',
+ misc: 'विविध',
+ rulesTitle: 'छात्रावास नियम एवं आचरण',
+ hostelDetails: {
+ name: 'छात्रावास का नाम: ',
+ overview: 'छात्रावास का अवलोकन',
+ staffOverview: 'छात्रावास स्टाफ का अवलोकन',
+ facilities: 'छात्रावास सुविधाओं का अवलोकन',
+ contact: 'हमसे संपर्क करें: ',
+ email: 'ईमेल: ',
+ wardens: 'वार्डन: ',
+ faculty: 'फैकल्टी',
+ staff: 'स्टाफ',
+ general: 'सामान्य',
+ hostelsStaffTable: {
+ name: 'नाम',
+ designation: 'पदनाम',
+ contact: 'संपर्क',
+ hostelPost: 'छात्रावास पद',
+ email: 'ईमेल',
+ },
+ },
+ },
Login: {
title: 'प्रवेश करें',
enterEmail: 'अपना ईमेल दर्ज करें',
diff --git a/i18n/translations.ts b/i18n/translations.ts
index 43127a89..71aa6fc5 100644
--- a/i18n/translations.ts
+++ b/i18n/translations.ts
@@ -90,6 +90,33 @@ export interface Translations {
login: string;
profile: { alt: string; view: string };
};
+ Hostels: {
+ title: string;
+ boysHostels: string;
+ girlsHostels: string;
+ misc: string;
+ notificationsTitle: string;
+ rulesTitle: string;
+ hostelDetails: {
+ name: string;
+ overview: string;
+ staffOverview: string;
+ facilities: string;
+ contact: string;
+ email: string;
+ wardens: string;
+ faculty: string;
+ staff: string;
+ general: string;
+ hostelsStaffTable: {
+ name: string;
+ designation: string;
+ hostelPost: string;
+ contact: string;
+ email: string;
+ };
+ };
+ };
Login: {
title: string;
enterEmail: string;
diff --git a/server/db/schema/notifications.schema.ts b/server/db/schema/notifications.schema.ts
index 2e27b0be..3ff7be97 100644
--- a/server/db/schema/notifications.schema.ts
+++ b/server/db/schema/notifications.schema.ts
@@ -14,7 +14,7 @@ export const notifications = pgTable(
title: varchar('title', { length: 256 }).unique().notNull(),
content: text('content'),
category: varchar('category', {
- enum: ['academic', 'tender', 'workshop', 'recruitment'],
+ enum: ['academic', 'tender', 'workshop', 'recruitment', 'hostel'],
}).notNull(),
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at')