Skip to content

Commit 5e81bee

Browse files
committed
Added a page for closed applications
1 parent ff98023 commit 5e81bee

20 files changed

Lines changed: 702 additions & 444 deletions
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Application Configuration System
2+
3+
This system allows you to easily control whether applications are open or closed across the entire website by changing just one setting.
4+
5+
## How to Use
6+
7+
### To Open Applications:
8+
1. Open `src/config/applicationConfig.ts`
9+
2. Set `googleFormUrl` to your Google Form URL:
10+
```typescript
11+
googleFormUrl: "https://forms.google.com/your-form-id",
12+
```
13+
14+
### To Close Applications:
15+
1. Open `src/config/applicationConfig.ts`
16+
2. Set `googleFormUrl` to `null` or empty string:
17+
```typescript
18+
googleFormUrl: null,
19+
// or
20+
googleFormUrl: "",
21+
```
22+
23+
## What Happens
24+
25+
- **When applications are OPEN**: All "Join Us" buttons will link to your Google Form and open in a new tab
26+
- **When applications are CLOSED**: All "Join Us" buttons will link to the "Application Period Closed" page
27+
28+
## Affected Components
29+
30+
The following components automatically use this configuration:
31+
- Desktop Navigation
32+
- Mobile Navigation
33+
- Hero Section
34+
- Footer
35+
- Contact Page
36+
- Team Member cards (for open positions)
37+
- Project cards (for recruiting projects)
38+
39+
## File Location
40+
41+
The configuration is located at:
42+
```
43+
src/config/applicationConfig.ts
44+
```
45+
46+
## Example Configuration
47+
48+
```typescript
49+
export const APPLICATION_CONFIG = {
50+
// Set this to your Google Form URL when applications are open
51+
googleFormUrl: "https://forms.google.com/your-actual-form-id",
52+
53+
// The system automatically detects if applications are open
54+
// and routes to the appropriate destination
55+
};
56+
```
57+
58+
## Benefits
59+
60+
-**Single source of truth** - Change one setting, affects entire site
61+
-**Automatic routing** - No need to update multiple files
62+
-**Professional fallback** - Shows proper "Application Closed" page when needed
63+
-**Easy maintenance** - No need to remember all the places to update
64+
-**Consistent behavior** - All application links behave the same way
File renamed without changes.

Source code/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Team from "./pages/Team";
1313
import Alumni from "./pages/Alumni";
1414
import Contact from "./pages/Contact";
1515
import Events from "./pages/Events";
16+
import ApplicationClosed from "./pages/ApplicationClosed";
1617
import NotFound from "./pages/NotFound";
1718

1819
const queryClient = new QueryClient();
@@ -33,6 +34,7 @@ const App = () => (
3334
<Route path="/alumni" element={<Alumni />} />
3435
<Route path="/events" element={<Events />} />
3536
<Route path="/contact" element={<Contact />} />
37+
<Route path="/apply" element={<ApplicationClosed />} />
3638
<Route path="*" element={<NotFound />} />
3739
</Routes>
3840
</main>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from "react";
2+
import { Link } from "react-router-dom";
3+
import { APPLICATION_CONFIG } from "@/config/applicationConfig";
4+
5+
interface ApplicationLinkProps {
6+
children: React.ReactNode;
7+
className?: string;
8+
variant?: "button" | "link";
9+
buttonProps?: React.ComponentProps<typeof Link> | React.AnchorHTMLAttributes<HTMLAnchorElement>;
10+
}
11+
12+
const ApplicationLink: React.FC<ApplicationLinkProps> = ({
13+
children,
14+
className = "",
15+
variant = "link",
16+
buttonProps = {}
17+
}) => {
18+
const isOpen = APPLICATION_CONFIG.isOpen;
19+
const url = APPLICATION_CONFIG.applicationUrl;
20+
const openInNewTab = APPLICATION_CONFIG.openInNewTab;
21+
22+
if (isOpen && openInNewTab) {
23+
// External link (Google Form) - opens in new tab
24+
return (
25+
<a
26+
href={url}
27+
target="_blank"
28+
rel="noopener noreferrer"
29+
className={className}
30+
{...buttonProps}
31+
>
32+
{children}
33+
</a>
34+
);
35+
} else {
36+
// Internal link (Application Closed page) - same tab
37+
return (
38+
<Link
39+
to={url}
40+
className={className}
41+
{...buttonProps}
42+
>
43+
{children}
44+
</Link>
45+
);
46+
}
47+
};
48+
49+
export default ApplicationLink;

Source code/src/components/DesktopNavigation.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import React from "react";
33
import { Link, useLocation } from "react-router-dom";
44
import { Button } from "@/components/ui/button";
5+
import ApplicationLink from "./ApplicationLink";
56

67
// Define navigation items for better maintainability
78
const navigationItems = [
@@ -37,14 +38,9 @@ const DesktopNavigation: React.FC<DesktopNavigationProps> = ({ isScrolled }) =>
3738
</Link>
3839
))}
3940

40-
<a
41-
href="https://forms.google.com/form"
42-
target="_blank"
43-
rel="noopener noreferrer"
44-
className="ml-4"
45-
>
41+
<ApplicationLink className="ml-4">
4642
<Button className="bg-primary-blue hover:bg-primary-blue/90 font-bold">Join Us</Button>
47-
</a>
43+
</ApplicationLink>
4844
</nav>
4945
);
5046
};

Source code/src/components/Footer.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
import React from "react";
33
import { Link } from "react-router-dom";
4+
import ApplicationLink from "./ApplicationLink";
45
import { Linkedin, Github, Mail } from "lucide-react";
56

67
const Footer = () => {
@@ -84,14 +85,11 @@ const Footer = () => {
8485
<p className="text-white/80 mb-2">Technical University Munich</p>
8586
<p className="text-white/80 mb-2">Munich, Germany</p>
8687
<p className="text-white/80 mb-4">Email: contact@open-hardware-initiative.com</p>
87-
<a
88-
href="https://forms.google.com/form"
89-
target="_blank"
90-
rel="noopener noreferrer"
88+
<ApplicationLink
9189
className="inline-block bg-white text-primary-blue px-4 py-2 rounded-md font-semibold hover:bg-white/90 transition-colors"
9290
>
9391
Join Us
94-
</a>
92+
</ApplicationLink>
9593
</div>
9694
</div>
9795

Source code/src/components/HeroSection.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import { Link } from "react-router-dom";
33
import { Button } from "@/components/ui/button";
44
import CircuitPattern from "@/components/CircuitPattern";
5+
import ApplicationLink from "./ApplicationLink";
56

67
const HeroSection = () => {
78
return (
@@ -45,11 +46,11 @@ const HeroSection = () => {
4546
Our Projects
4647
</Button>
4748
</Link>
48-
<a href="https://forms.google.com/form" target="_blank" rel="noopener noreferrer" className="w-full sm:w-auto">
49+
<ApplicationLink className="w-full sm:w-auto">
4950
<Button variant="outline" size="lg" className="w-full sm:w-auto border-bistre text-bistre hover:bg-bistre/5 text-base sm:text-lg px-6 sm:px-8 py-3 sm:py-4">
5051
Join Our Team
5152
</Button>
52-
</a>
53+
</ApplicationLink>
5354
</div>
5455
</div>
5556
</div>

Source code/src/components/MobileNavigation.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import React from "react";
33
import { Link, useLocation } from "react-router-dom";
44
import { Button } from "@/components/ui/button";
5+
import ApplicationLink from "./ApplicationLink";
56

67
interface NavLinkProps {
78
to: string;
@@ -64,19 +65,16 @@ const MobileNavigation: React.FC<MobileNavigationProps> = ({ isMenuOpen, locatio
6465
<MobileNavLink to="/contact" isActive={isActive("/contact")} delay={400} isMenuOpen={isMenuOpen}>
6566
Contact
6667
</MobileNavLink>
67-
<a
68-
href="https://forms.google.com/form"
69-
target="_blank"
70-
rel="noopener noreferrer"
68+
<ApplicationLink
7169
className={`mt-8 w-4/5 transition-all duration-300 transform ${
7270
isMenuOpen ? "translate-y-0 opacity-100" : "-translate-y-4 opacity-0"
7371
}`}
74-
style={{ transitionDelay: "450ms" }}
72+
buttonProps={{ style: { transitionDelay: "450ms" } }}
7573
>
7674
<Button className="bg-primary-blue hover:bg-primary-blue/90 font-bold text-xl w-full py-6">
7775
Join Us
7876
</Button>
79-
</a>
77+
</ApplicationLink>
8078
</nav>
8179
</div>
8280
);

Source code/src/components/ProjectCard.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
66
import { Project } from "@/data/projectsData";
77
import { getStringBasedColor, getContrastTextColor } from "@/utils/colorUtils";
88
import { Link } from "react-router-dom";
9+
import ApplicationLink from "./ApplicationLink";
910

1011
interface ProjectCardProps {
1112
project: Project;
@@ -136,12 +137,12 @@ const ProjectCard: React.FC<ProjectCardProps> = ({ project }) => {
136137
)}
137138

138139
{recruitingFor && (
139-
<Link to="/contact" className="flex-shrink-0">
140+
<ApplicationLink className="flex-shrink-0">
140141
<Button variant="default" className="flex items-center gap-2" size="sm">
141142
<UserPlus size={16} className="flex-shrink-0" />
142143
<span className="sm:inline hidden">Join</span>
143144
</Button>
144-
</Link>
145+
</ApplicationLink>
145146
)}
146147
</CardFooter>
147148
</Card>

Source code/src/components/TeamMember.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Card } from "@/components/ui/card";
33
import { Linkedin, UserPlus } from "lucide-react";
44
import TeamMemberImage from "./TeamMemberImage";
55
import { Link } from "react-router-dom";
6+
import ApplicationLink from "./ApplicationLink";
67

78
interface TeamMemberProps {
89
name: string;
@@ -111,13 +112,12 @@ const TeamMember: React.FC<TeamMemberProps> = ({
111112
</a>
112113
) : null}
113114
{isOpenPosition && (
114-
<Link
115-
to="/contact"
115+
<ApplicationLink
116116
className="absolute bottom-4 right-4 p-2 bg-white text-primary-blue rounded-full hover:bg-primary-blue hover:text-white transition-colors"
117-
aria-label="Apply for this position"
117+
buttonProps={{ "aria-label": "Apply for this position" }}
118118
>
119119
<UserPlus size={18} />
120-
</Link>
120+
</ApplicationLink>
121121
)}
122122
</div>
123123
<div className="p-4">
@@ -126,12 +126,11 @@ const TeamMember: React.FC<TeamMemberProps> = ({
126126
<p className="text-gray-600 text-sm mt-1 line-clamp-2">{education}</p>
127127
)}
128128
{isOpenPosition && (
129-
<Link
130-
to="/contact"
129+
<ApplicationLink
131130
className="inline-block mt-3 text-sm font-medium text-primary-blue hover:underline"
132131
>
133132
Apply Now →
134-
</Link>
133+
</ApplicationLink>
135134
)}
136135
</div>
137136
</Card>

0 commit comments

Comments
 (0)