Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ A map visualizer where researchers designers or the community can submit a propo
## Tech stack

- [Tailwind](https://tailwindcss.com/) for style composition
- [Lucide](https://lucide.dev/) for Icons
- [LeafLet](https://react-leaflet.js.org/) for Maps and Map Containers
- [React](https://reactjs.org/) for building declarative, component-based user interfaces
- [Typescript](https://www.typescriptlang.org/) for static type checking
- [Vite](https://vitejs.dev/) as a build tool for fast and lean dev experience
- [Vitest](https://vitest.dev/) for unit-testing
- [Papaparse](https://www.papaparse.com/) for parsing CSV files

## Install

Expand Down
58 changes: 43 additions & 15 deletions src/components/ProposalList.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
import React from 'react';
import { Clock, CheckCircle, XCircle, FileText, Link } from 'lucide-react';
import type { Proposal } from '../types/proposal';
import React from "react";
import { Clock, CheckCircle, XCircle, FileText, Link } from "lucide-react";
import type { Proposal } from "../types/proposal";

interface ProposalListProps {
proposals: Proposal[];
}

export default function ProposalList({ proposals }: ProposalListProps) {
const getStatusIcon = (status: Proposal['status']) => {
const getStatusIcon = (status: Proposal["status"]) => {
switch (status) {
case 'approved':
case "approved":
return <CheckCircle className="h-5 w-5 text-green-500" />;
case 'rejected':
case "rejected":
return <XCircle className="h-5 w-5 text-red-500" />;
default:
return <Clock className="h-5 w-5 text-yellow-500" />;
}
};

const getStatusColor = (status: Proposal['status']) => {
const getStatusColor = (status: Proposal["status"]) => {
switch (status) {
case 'approved':
return 'bg-green-100 text-green-800';
case 'rejected':
return 'bg-red-100 text-red-800';
case "approved":
return "bg-green-100 text-green-800";
case "rejected":
return "bg-red-100 text-red-800";
default:
return 'bg-yellow-100 text-yellow-800';
return "bg-yellow-100 text-yellow-800";
}
};

return (
<div className="space-y-6">
{proposals.map((proposal) => (
{/* {proposals.map((proposal) => (
<div
key={proposal.id}
className="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow"
Expand Down Expand Up @@ -91,7 +91,35 @@ export default function ProposalList({ proposals }: ProposalListProps) {
Submitted on {new Date(proposal.createdAt).toLocaleDateString()}
</div>
</div>
))}
))} */}
{/*
<iframe
class="airtable-embed"
src="https://airtable.com/embed/appm28CKlTjcv9TEb/shrkRxOQRoxO3JAx2"
// frameborder="0"
// onmousewheel=""
width="100%"
height="533"
// style="background: transparent; border: 1px solid #ccc;"
/> */}
{/*
<iframe
// class="airtable-embed"
src="https://airtable.com/embed/appNfh2f9RGsdETXE/shr30Xx91cpUqCmm2?viewControls=on"
// frameborder="0"
// onmousewheel=""
width="100%"
height="533"
style={{ background: "transparent", border: "1px solid #ccc" }}
></iframe> */}

<iframe
src="https://airtable.com/embed/appNfh2f9RGsdETXE/shr30Xx91cpUqCmm2?viewControls=on"
// frameborder="0"
// onmousewheel=""
width="100%"
height="600"
></iframe>
</div>
);
}
}
98 changes: 71 additions & 27 deletions src/components/ProposalPage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import React, { useState } from 'react';
import { PlusCircle, Linkedin } from 'lucide-react';
import type { Proposal } from '../types/proposal';
import ProposalForm from './ProposalForm';
import React, { useState } from "react";
import { PlusCircle, Linkedin, X } from "lucide-react";
import type { Proposal } from "../types/proposal";
import ProposalForm from "./ProposalForm";
import ProposalList from "./ProposalList";

interface ProposalPageProps {
proposals: Proposal[];
onSubmit: (proposal: Omit<Proposal, 'id' | 'status' | 'createdAt'>) => void;
onSubmit: (proposal: Omit<Proposal, "id" | "status" | "createdAt">) => void;
}

export default function ProposalPage({ proposals, onSubmit }: ProposalPageProps) {
export default function ProposalPage({
proposals,
onSubmit,
}: ProposalPageProps) {
const [showForm, setShowForm] = useState(false);

return (
Expand All @@ -26,27 +30,53 @@ export default function ProposalPage({ proposals, onSubmit }: ProposalPageProps)

{showForm && (
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-xl p-6 max-w-2xl w-full mx-4">
{/* <div className="bg-white rounded-lg shadow-xl p-6 max-w-2xl w-full mx-4">
<ProposalForm
onSubmit={(data) => {
onSubmit(data);
setShowForm(false);
}}
onClose={() => setShowForm(false)}
/>
</div>
</div> */}
{/* <div className="bg-white rounded-lg shadow-xl p-6 max-w-2xl w-full mx-4">
{/* <ProposalForm
onSubmit={data => {
onSubmit(data);
setShowForm(false);
}}
onClose={() => setShowForm(false)}
/> */}
<button onClick={() => setShowForm(false)}>
<X />
</button>

<iframe
// class="airtable-embed"
src="https://airtable.com/embed/appNfh2f9RGsdETXE/pagmAsLJdWX9VQcOU/form"
// frameborder="0"
// onmousewheel=""
width="100%"
height="533"
// style="background: transparent; border: 1px solid #ccc;"
/>
</div>
)}

<div className="grid grid-cols-1 gap-6">
{proposals.map((proposal) => (
<div
className="grid grid-cols-1 gap-6"
style={{ border: "solid 2px pink" }}
>
{/* {proposals.map(proposal => (
<div
key={proposal.id}
className="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow"
>
<div className="space-y-4">
<div>
<h3 className="text-xl font-semibold text-gray-900">{proposal.title}</h3>
<h3 className="text-xl font-semibold text-gray-900">
{proposal.title}
</h3>
<p className="mt-1 text-sm text-gray-500">
Submitted by {proposal.contactName} • {proposal.organization}
</p>
Expand All @@ -55,25 +85,33 @@ export default function ProposalPage({ proposals, onSubmit }: ProposalPageProps)
<div className="prose max-w-none">
<div className="space-y-4">
<div>
<h4 className="text-lg font-medium text-gray-900">Research Summary</h4>
<h4 className="text-lg font-medium text-gray-900">
Research Summary
</h4>
<p className="mt-1 text-gray-600">{proposal.description}</p>
</div>

{proposal.researchImportance && (
<div>
<h4 className="text-lg font-medium text-gray-900">Why is this Research Important?</h4>
<p className="mt-1 text-gray-600">{proposal.researchImportance}</p>
<h4 className="text-lg font-medium text-gray-900">
Why is this Research Important?
</h4>
<p className="mt-1 text-gray-600">
{proposal.researchImportance}
</p>
</div>
)}
</div>
</div>

<div>
<h4 className="font-medium text-gray-900">Contact Information</h4>
<h4 className="font-medium text-gray-900">
Contact Information
</h4>
<div className="mt-2 space-y-1 text-gray-600">
<p>{proposal.contactName}</p>
<p>{proposal.email}</p>
<a
<a
href={proposal.linkedinUrl}
target="_blank"
rel="noopener noreferrer"
Expand All @@ -87,22 +125,28 @@ export default function ProposalPage({ proposals, onSubmit }: ProposalPageProps)

<div className="flex items-center justify-between pt-4 border-t border-gray-200">
<span className="text-sm text-gray-500">
Submitted on {new Date(proposal.createdAt).toLocaleDateString()}
Submitted on{" "}
{new Date(proposal.createdAt).toLocaleDateString()}
</span>
<span className={`px-3 py-1 text-sm font-medium rounded-full ${
proposal.status === 'approved'
? 'bg-green-100 text-green-800'
: proposal.status === 'rejected'
? 'bg-red-100 text-red-800'
: 'bg-yellow-100 text-yellow-800'
}`}>
{proposal.status.charAt(0).toUpperCase() + proposal.status.slice(1)}
<span
className={`px-3 py-1 text-sm font-medium rounded-full ${
proposal.status === "approved"
? "bg-green-100 text-green-800"
: proposal.status === "rejected"
? "bg-red-100 text-red-800"
: "bg-yellow-100 text-yellow-800"
}`}
>
{proposal.status.charAt(0).toUpperCase() +
proposal.status.slice(1)}
</span>
</div>
</div>
</div>
))}
))} */}

<ProposalList proposals={[]} />
</div>
</div>
);
}
}