Skip to content

Commit

Permalink
9 interview card data (#24)
Browse files Browse the repository at this point in the history
* data initial render

* topic cards adjusted

* data fetching for card server components

* refactored topic sorting

* prettier
  • Loading branch information
jtmst authored May 8, 2024
1 parent 3f07a46 commit 282ed98
Show file tree
Hide file tree
Showing 204 changed files with 6,452 additions and 4,823 deletions.
8,138 changes: 4,698 additions & 3,440 deletions .pnp.cjs

Large diffs are not rendered by default.

1,249 changes: 878 additions & 371 deletions .pnp.loader.mjs

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{
"recommendations": ["arcanis.vscode-zipfs", "dbaeumer.vscode-eslint"]
"recommendations": [
"arcanis.vscode-zipfs",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
},
"eslint.nodePath": ".yarn/sdks",
"typescript.tsdk": ".yarn/sdks/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
"typescript.enablePromptUseWorkspaceTsdk": true,
"prettier.prettierPath": ".yarn/sdks/prettier/index.cjs"
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed .yarn/cache/has-npm-1.0.3-b7f00631c1-a449f3185b.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed .yarn/cache/open-npm-9.1.0-d104a17ec5-b45bcc7a67.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion .yarnrc.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
yarnPath: ".yarn/releases/yarn-3.6.1.cjs"
yarnPath: '.yarn/releases/yarn-3.6.1.cjs'
6 changes: 0 additions & 6 deletions formSources.config.js

This file was deleted.

4 changes: 2 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const isProd = process.env.NODE_ENV === 'production';

const nextConfig = {
output: 'export',
basePath: isProd ? '/courtformsonline.org' : '',
assetPrefix: isProd ? '/courtformsonline.org' : '',
// basePath: isProd ? '/courtformsonline.org' : '',
// assetPrefix: isProd ? '/courtformsonline.org' : '',
images: {
unoptimized: true,
},
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next",
"build": "next build",
"start": "next start",
"start": "serve out",
"lint": "next lint",
"format": "prettier --write .",
"test:format": "prettier --check 'src/**/*.js'"
Expand All @@ -28,7 +28,9 @@
"react-bootstrap": "^2.7.4",
"react-dom": "18.2.0",
"react-icons": "^5.0.1",
"reactstrap": "^9.1.9"
"reactstrap": "^9.1.9",
"serve": "^14.2.3",
"swr": "^2.2.5"
},
"devDependencies": {
"@types/bootstrap": "^5.2.6",
Expand Down
2 changes: 1 addition & 1 deletion src/app/[topic]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GetStaticPathsResult } from 'next';
import { legalTopics, Topic } from '../../../topics.config';
import { legalTopics, Topic } from '../../config/topics.config';

interface PageProps {
params: {
Expand Down
57 changes: 57 additions & 0 deletions src/app/components/TopicCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Link from 'next/link';

interface TopicCardProps {
topic: {
name: string;
long_name: string;
icon: string;
};
interviews: any[];
}

interface IconProps {
iconName: string;
className?: string;
style?: React.CSSProperties;
}

const FontAwesomeIcon = ({ iconName, className = '' }: IconProps) => {
return <i className={`fas fa-${iconName} ${className}`}></i>;
};

const TopicCard = ({ topic, interviews }: TopicCardProps) => {
// Display the first 3 interviews, and show a final tag with how many remaining interviews are not shown
const displayInterviews = interviews.slice(0, 3);
const extraCount = interviews.length > 3 ? interviews.length - 3 : 0;

return (
<div className="col-lg-4">
<Link
href={`/${topic.name.toLowerCase()}`}
className="text-decoration-none text-dark"
>
<div className="card m-1 topic-card h-100">
<div className="card-header d-flex align-items-center">
<div
style={{ minWidth: '40px', minHeight: '40px' }}
className="icon-container d-inline-flex justify-content-center align-items-center rounded"
>
<FontAwesomeIcon iconName={topic.icon} className="fa-icon" />
</div>
<h5 className="card-title ms-3">{topic.long_name}</h5>
</div>
<div className="card-body">
{displayInterviews.map((interview, index) => (
<span key={index} className="form-tag">
{interview.metadata.title}
</span>
))}
{extraCount > 0 && <span className="form-tag">+{extraCount}</span>}
</div>
</div>
</Link>
</div>
);
};

export default TopicCard;
25 changes: 13 additions & 12 deletions src/app/forms/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Form } from '../interfaces/Form';
import InteractiveForm from '../components/InteractiveForm';
import serverList from '../../../formSources.config.js';
import { formSources } from '../../config/formSources.config';

interface LegalFormsPageProps {
forms: Form[];
Expand All @@ -9,33 +9,34 @@ interface LegalFormsPageProps {
async function getData() {
let allData: Form[] = [];

for (const [serverName, serverUrl] of Object.entries(
serverList['docassemble servers']
)) {
const url = new URL(serverUrl);
// Iterating over an array of server objects
for (const server of formSources.docassembleServers) {
const url = new URL(server.url); // Access the URL directly from the server object
url.pathname = '/list';
url.search = 'json=1';

const res = await fetch(url);
const res = await fetch(url.toString());

// Recommendation: handle errors
// Handle errors
if (!res.ok) {
console.error(`Failed to fetch data from ${serverUrl}`);
console.error(`Failed to fetch data from ${server.url}`);
continue; // Skip this server and continue with the next one
}

const data = await res.json();

if (!data.hasOwnProperty('interviews')) {
console.error(`Data from ${serverUrl} does not contain "interviews" key`);
console.error(
`Data from ${server.url} does not contain "interviews" key`
);
continue; // Skip this server and continue with the next one
}

// If you want to include the server name and server URL in the data:
// Include the server name and server URL in the data
const interviews = data['interviews'].map((interview: Form) => ({
...interview,
serverName,
serverUrl,
serverName: server.name,
serverUrl: server.url,
}));

allData = allData.concat(interviews);
Expand Down
104 changes: 19 additions & 85 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,14 @@
import Link from 'next/link';
import React from 'react';
import HeroSection from './components/HeroSection';
import HowItWorksSection from './components/HowItWorksSection';
import { Topic } from '../../topics.config';
import { fetchInterviews } from '../data/fetchInterviewData';
import TopicCard from './components/TopicCard';
import { legalTopics } from '../config/topics.config';

const { legalTopics, findParentTopic } = require('../../topics.config.ts');
export default async function TopicsPage() {
const interviewsResult = await fetchInterviews();
const { interviewsByTopic } = interviewsResult;

interface IconProps {
iconName: string;
className: string;
}

const FontAwesomeIcon: React.FC<IconProps> = ({ iconName, className = '' }) => {
return <i className={`fas fa-${iconName} ${className}`}></i>;
};

const fakeFormNames = [
'Fee waiver',
'209A Domestic Violence Restraining Order',
'Enlarge Time to File (Appeals Court)',
'Appeal or Stay Your Eviction',
'Eviction Moratorium',
'Civil Docketing Statement',
'Massachusetts Defense for Eviction (MADE)',
'Dismiss your CRA case',
'Interpreter Notice',
'Petition to Change Name of Adult',
];

const getRandomItems = (arr: Array<string>, min: number, max: number) => {
const newArr = [...arr]; // Copy array to avoid mutating the original one.
let count = Math.floor(min + Math.random() * (max - min + 1));
let result: Array<string> = [];
while (count--) {
result.push(newArr.splice(Math.floor(Math.random() * newArr.length), 1)[0]);
}
return result;
};

// const formPill

const TopicCard = ({ topic }: { topic: Topic }) => (
<div className="col-lg-4">
<Link
href={`/${topic.name.toLowerCase()}`}
className="text-decoration-none text-dark"
>
<div className="card m-1 topic-card h-100">
<div className="card-header d-flex align-items-center">
<div
style={{ minWidth: '40px', minHeight: '40px' }}
className="icon-container d-inline-flex justify-content-center align-items-center rounded"
>
<FontAwesomeIcon iconName={topic.icon} className="fa-icon" />
</div>
<h5 className="card-title ms-3">{topic.long_name}</h5>
</div>
<div className="card-body">
{getRandomItems(fakeFormNames, 2, 5).map((form: string) => (
<span key={form} className="form-tag">
{form}
</span>
))}
<span className="form-tag">+2</span>
</div>
</div>
</Link>
</div>
);

export default function TopicsPage() {
return (
<div>
<HeroSection />
Expand All @@ -79,29 +18,24 @@ export default function TopicsPage() {
<h2>Browse court forms by category</h2>
<div className="row row-cols-1 row-cols-md-3 g-5">
{legalTopics
.sort((a: Topic, b: Topic) => (a.priority < b.priority ? 1 : -1))
.filter((topic: Topic) => topic.always_visible)
.map((topic: Topic) => (
<TopicCard key={topic.codes[0]} topic={topic} />
.sort((a, b) => b.priority - a.priority)
.filter(
(topic) =>
topic.always_visible ||
(interviewsByTopic[topic.name] &&
interviewsByTopic[topic.name].length > 0)
)
.map((topic) => (
<TopicCard
key={topic.codes[0]}
topic={topic}
interviews={interviewsByTopic[topic.name] || []}
/>
))}
</div>
<Link href="#">Show all categories</Link>
</div>
</section>
<div className="container">
<div className="row mt-4">
<div className="col">
<h2>About</h2>
<p>
Court Forms Online is operated by Suffolk University Law School's
Legal Innovation and Technology Lab. It began as a volunteer
project in cooperation with the Massachusetts Access to Justice
Commission's COVID-19 task force and volunteers from around the
world. <Link href="/about">Learn more...</Link>
</p>
</div>
</div>
</div>
</div>
);
}
14 changes: 14 additions & 0 deletions src/config/formSources.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const formSources = {
docassembleServers: [
{
key: 'suffolkListLab',
url: 'https://apps.suffolklitlab.org',
name: 'Suffolk LIT Lab',
},
{
key: 'greaterBostonLegalService',
url: 'https://interviews.gbls.org',
name: 'Greater Boston Legal Services',
},
],
};
Loading

0 comments on commit 282ed98

Please sign in to comment.