Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6c1d7c2
Update .gitignore
ashidtuguldur Dec 10, 2025
caf8a0f
getting data from @/app/events/page getEvents function
ashidtuguldur Dec 10, 2025
d6cc4c4
Merge remote-tracking branch 'origin/main' into 57-banner-on-home-pag…
ashidtuguldur Dec 10, 2025
1941ce0
Merge branch 'main' into 57-banner-on-home-page-for-announcements
ashidtuguldur Dec 24, 2025
cd2c3b1
getting time and comparing
ashidtuguldur Dec 24, 2025
8abfde0
EVENT URL CHECK
ashidtuguldur Dec 30, 2025
bdb7bdf
Merge branch 'main' into 57-banner-on-home-page-for-announcements
ashidtuguldur Jan 4, 2026
cb3197e
URL CHECK
ashidtuguldur Feb 5, 2026
9a168a2
bla bla bla
ashidtuguldur Feb 5, 2026
94131f2
Update meta desc to _the_ social CS club (#119)
edwardshturman Jan 17, 2026
74fa8c2
getting time and comparing
ashidtuguldur Dec 24, 2025
309a0a4
Home page banner render testing one
ashidtuguldur Feb 7, 2026
30d9dc5
Merge branch 'main' into 57-banner-on-home-page-for-announcements
ashidtuguldur Feb 7, 2026
87aa3b7
Extend `LinkBar`
edwardshturman Feb 13, 2026
27f8a12
Merge branch 'main' into 57-banner-on-home-page-for-announcements
edwardshturman Feb 13, 2026
27dfb52
Fix lockfile
edwardshturman Feb 13, 2026
5db24bc
Delete `coverage/` dir
edwardshturman Feb 13, 2026
d7c91f2
Centralize Jest setup
edwardshturman Feb 13, 2026
52ff608
Adjust test to correct expected case
edwardshturman Feb 13, 2026
3f09fbf
Use `next/jest`
edwardshturman Feb 13, 2026
e2e42ed
Format `app/page.tsx`
edwardshturman Feb 14, 2026
deb3ce2
Merge branch 'main' into 57-banner-on-home-page-for-announcements
edwardshturman Feb 16, 2026
058ee8f
Fix lockfile
edwardshturman Feb 16, 2026
11fee7e
Merge branch 'main' into 57-banner-on-home-page-for-announcements
edwardshturman Feb 16, 2026
97d5888
Update lockfile
edwardshturman Feb 16, 2026
4e9de72
Merge branch 'main' into 57-banner-on-home-page-for-announcements
edwardshturman Feb 16, 2026
cc80dbb
Merge branch 'main' into 57-banner-on-home-page-for-announcements
edwardshturman Feb 16, 2026
0d557d2
Merge branch 'main' of https://github.com/compsigh/web into 57-banner…
edwardshturman Feb 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ next-env.d.ts

# Nix
flake.lock
.env*.local
2 changes: 1 addition & 1 deletion app/events/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import styles from './Events.module.css'
type CompleteEventDetails = EventDetails & { end: number, link: string | null }
export type EventFrontmatter = Omit<Frontmatter, 'event_details'> & { event_details: CompleteEventDetails }

async function getEvents() {
export async function getEvents() {
const markdownFiles = await generateUnmodifiedSlugsFromMarkdownFiles('app/events')
const events: Frontmatter[] = []
for (const { slug } of markdownFiles) {
Expand Down
7 changes: 6 additions & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { NavItems } from "@/components/NavItems"
import { HomeLoop } from "@/components/HomeLoop"
import { HomepageBanner } from "@/components/HomepageBanner"
import { getEvents } from "./events/page"

import styles from "./Home.module.css"

export default function Home() {
export default async function Home() {
const events = await getEvents()

return (
<>
<div id={styles.content}>
<HomepageBanner events={events} />
<h1 id={styles.title}>compsigh</h1>
<p id={styles.description}>
compsigh is the social computer science club at USFCA for meeting cool
Expand Down
19 changes: 19 additions & 0 deletions components/HomepageBanner/HomepageBanner.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
div.banner {
/*font-size: 1.2rem;*/

/*a {
display: flex;
white-space: pre;
text-decoration: none;
padding: 4px 8px;
}*/
}

@media (max-width: 700px) {
div.banner {
margin-left: -24px;
/*a {
flex-direction: column;
}*/
}
}
33 changes: 33 additions & 0 deletions components/HomepageBanner/HomepageBanner.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { render, screen } from "@testing-library/react"
import { HomepageBanner } from "./HomepageBanner"
import { EventFrontmatter } from "@/app/events/page"

describe("Next Component HomepageBanner", () => {
it("Renders when an event is coming up", () => {
const currentTime = Math.floor(new Date().getTime() / 1000)

const testing_UpComingEvent: EventFrontmatter[] = [
{
title: "DAVE",
description: "register!",
event_details: {
start: currentTime + 60,
end: currentTime + 90,
location: "The Hive",
cover_image: "/events/2025-11-07/deploy25.png",
pictures: [],
link: "https://touch-grass.tech/"
},
slug: "events/2025-11-07/deploy25"
}
]

render(<HomepageBanner events={testing_UpComingEvent} />)

const banner = screen.getByText((content) =>
content.includes("Next event:")
)

expect(banner).toBeInTheDocument()
})
})
63 changes: 63 additions & 0 deletions components/HomepageBanner/HomepageBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"use client"

// Components
import { LinkBar } from "@/components/LinkBar"

// Functions
import { isValidURL } from "./isValidURL"

// Types
import { EventFrontmatter } from "@/app/events/page"

// Styles
import styles from "./HomepageBanner.module.css"

export function HomepageBanner({ events }: { events: EventFrontmatter[] }) {
const currentTime = Math.floor(new Date().getTime() / 1000)
if (events.length === 0) return <></>

const updatedEvents: EventFrontmatter[] = [
...events,
{
title: "compsigh night v2026.01.20 6 7",
description: "register!",
event_details: {
start: 1770420908,
end: 1770420968,
location: "The Hive",
cover_image: "/events/2025-11-07/deploy25.png",
pictures: [],
link: "https://touch-grass.tech/"
},
slug: "events/2025-11-07/deploy25"
}
]

const upcomingEvents: EventFrontmatter[] = []
for (const event of updatedEvents)
if (currentTime < event.event_details.start) upcomingEvents.push(event)

if (upcomingEvents.length === 0) return <></>
const nearestUpcomingEvent = upcomingEvents[0]
const title = nearestUpcomingEvent.title
const eventLink = nearestUpcomingEvent.event_details.link!

if (!isValidURL(eventLink)) return <></>

return (
<div className={styles.banner}>
{/*<Link href={eventLink} style={{ fontFamily: "var(--font-tronica-mono)" }}>
<span>Next event: </span>
<TextStream duration={1} text={`${title} >`} />
</Link>*/}
<LinkBar
arrowDirection="forward"
alignment="end"
order="text-first"
href={"https://compsigh.club"}
>
Next event: {title}
</LinkBar>
</div>
)
}
1 change: 1 addition & 0 deletions components/HomepageBanner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { HomepageBanner } from './HomepageBanner'
89 changes: 89 additions & 0 deletions components/HomepageBanner/isValidURL.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { isValidURL } from "./isValidURL"

interface Test {
name: string
input: string
expected: boolean
}

const tests: Test[] = [
{
name: "Return true for valid URL string",
input: "https://touch-grass.tech/",
expected: true
},
{
name: "File Transfer Protocol",
input: "ftp://example.com",
expected: true
},
{
name: "WebSocket Secure Protocol",
input: "wss://example.com",
expected: true
},
{
name: "Email Protocol",
input: "mailto://johnpork@yahoo.com",
expected: true
},
{
name: "Torrent Protocol",
input:
"magnet:?xt=urn:btih:6D5B5F0E8E6E4F5D8B7A9C1E2D3F4A5B6C7D8E9F&dn=example-file.zip&tr=udp://tracker.example.com:6969/announce",
expected: true
},
{
name: "Missing protocol",
input: "example.com",
expected: false
},
{
name: "Fake protocol",
input: "67://example.com",
expected: false
},
{
name: "Space in domain name",
input: "https://example .com",
expected: false
},
{
name: "Space in domain",
input: "https://exam ple.com/path",
expected: false
},
{
name: "No colon after protocol",
input: "ftp//example.com",
expected: false
},
{
name: "Missing one slash",
input: "https:/example.com",
expected: true
},
{
name: "Extra slash",
input: "https:////////////////example.com",
expected: true
},
{
name: "Non-numeric port",
input: "https://exam[ple].com",
expected: false
},
{
name: "Unencoded spaces in path",
input: "https://tungtungtung.com/path with spaces",
expected: true
}
]

describe("TS function IsValidURL", () => {
tests.forEach((config) => {
it(config.name, () => {
expect(isValidURL(config.input)).toBe(config.expected)
})
})
})
8 changes: 8 additions & 0 deletions components/HomepageBanner/isValidURL.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function isValidURL(url: string): boolean {
try {
new URL(url)
return true
} catch {
return false
}
}
15 changes: 13 additions & 2 deletions components/LinkBar/LinkBar.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,23 @@ div#container {
width: 100%;
height: 64px;
display: flex;
justify-content: flex-end;
align-items: center;
font-family: var(--font-tronica-mono);
}

div#container.previous {
div#container.alignment-start {
justify-content: left;
}

div#container.alignment-end {
justify-content: right;
}

div#container.text-first {
flex-direction: row;
}

div#container.arrow-first {
flex-direction: row-reverse;
}

Expand Down
25 changes: 19 additions & 6 deletions components/LinkBar/LinkBar.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import Link, { type LinkProps } from 'next/link'
import Link, { type LinkProps } from "next/link"

import styles from './LinkBar.module.css'
import styles from "./LinkBar.module.css"

interface LinkBarProps extends LinkProps {
children: React.ReactNode
type?: 'previous' | 'next'
arrowDirection?: "back" | "forward"
alignment?: "start" | "end"
order?: "text-first" | "arrow-first"
}

export function LinkBar({ children, type = 'next', ...props }: LinkBarProps) {
export function LinkBar({
children,
arrowDirection = "forward",
alignment = "end",
order = "text-first",
...props
}: LinkBarProps) {
return (
<div id={styles["link-container"]}>
<Link {...props}>
<div
id={styles.container}
className={type === 'next' ? styles.next : styles.previous}
className={`
${order === "text-first" ? styles["text-first"] : styles["arrow-first"]}
${alignment === "start" ? styles["alignment-start"] : styles["alignment-end"]}
`}
>
<div id={styles.bar} />
<div>{children}</div>
<div id={styles.arrow}>{type === 'next' ? '>' : '<'}</div>
<div id={styles.arrow}>
{arrowDirection === "forward" ? ">" : "<"}
</div>
</div>
</Link>
</div>
Expand Down
14 changes: 12 additions & 2 deletions components/PostWrapper/PostWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,25 @@ function AuthorsAndContent({ content, frontmatter }: PostProps) {
{frontmatter.previous && (
<>
<Spacer size={32} />
<LinkBar type="previous" href={frontmatter.previous.link}>
<LinkBar
arrowDirection="back"
alignment="start"
order="arrow-first"
href={frontmatter.previous.link}
>
{frontmatter.previous.text}
</LinkBar>
</>
)}
{frontmatter.next && (
<>
<Spacer size={32} />
<LinkBar type="next" href={frontmatter.next.link}>
<LinkBar
arrowDirection="forward"
alignment="end"
order="text-first"
href={frontmatter.next.link}
>
{frontmatter.next.text}
</LinkBar>
</>
Expand Down
12 changes: 12 additions & 0 deletions jest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import nextJest from 'next/jest.js'

const createJestConfig = nextJest({
dir: './',
})

const config = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}

export default createJestConfig(config)
1 change: 1 addition & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@testing-library/jest-dom'
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
"prebuild": "pnpm run lint",
"build": "next build --turbopack",
"start": "next start",
"migrate": "dotenv -e .env.local prisma migrate dev"
"migrate": "dotenv -e .env.local prisma migrate dev",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
},
"dependencies": {
"@prisma/client": "6.5.0",
Expand All @@ -43,10 +46,15 @@
"use-sound": "5.0.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@types/howler": "2.2.12",
"@types/jest": "^29.5.0",
"@types/node": "25.2.3",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"eslint": "9.39.1",
"eslint-config-next": "16.1.6",
"next-devtools-mcp": "0.3.10",
Expand Down
Loading