Skip to content

Commit

Permalink
Chore/refactor into components (#7)
Browse files Browse the repository at this point in the history
* move GA to layout. component folders

* organize into components
  • Loading branch information
steezeburger authored Aug 17, 2024
1 parent 3bf3713 commit 4ce9bde
Show file tree
Hide file tree
Showing 10 changed files with 282 additions and 250 deletions.
8 changes: 6 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ web-install:
cd web && npm install

# builds the typescript for the front end app
build-web:
web-build:
cd web && npm run build

# run front end app locally,
# with file watching that triggers rebuilds
web-run:
cd web && npm run dev
cd web && npm run dev

# lint the front end app
web-lint:
cd web && npm run lint
6 changes: 5 additions & 1 deletion web/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { GoogleAnalytics } from "@next/third-parties/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });
Expand All @@ -17,7 +18,10 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body className={inter.className}>
{children}
<GoogleAnalytics gaId="G-XFQJZD9P2K" />
</body>
</html>
);
}
6 changes: 3 additions & 3 deletions web/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"use client";

import React from "react";
import WikipediaBrowser from "../components/WikipediaBrowser";
import { GoogleAnalytics } from "@next/third-parties/google";
import WikipediaBrowser from "@/components/WikipediaBrowser/WikipediaBrowser";


const Home: React.FC = () => {
return (
<div>
<WikipediaBrowser />
<GoogleAnalytics gaId="G-XFQJZD9P2K" />
</div>
);
};
Expand Down
94 changes: 94 additions & 0 deletions web/src/components/Pane/Pane.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React, { memo, useEffect, useRef } from "react";
import Pane from "@/components/Pane/types";

const Resizer = memo(({ onResize }: { onResize: (delta: number) => void }) => {
const startResizeX = useRef(0);

const handleMouseDown = (e: React.MouseEvent) => {
e.preventDefault();
startResizeX.current = e.clientX;
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
};

const handleMouseMove = (e: MouseEvent) => {
const delta = e.clientX - startResizeX.current;
onResize(delta);
startResizeX.current = e.clientX;
};

const handleMouseUp = () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};

return (
<div
className="resizer w-1 bg-gray-300 cursor-col-resize hover:bg-gray-400 transition-colors absolute top-0 right-0 bottom-0"
onMouseDown={handleMouseDown}
/>
);
});
Resizer.displayName = "Resizer";

const PaneComponent = memo(({ pane, index, onClose, onClick, clickedLinks, onResize, isFocused }: {
pane: Pane;
index: number;
onClose: (index: number) => void;
onClick: (e: React.MouseEvent<HTMLDivElement>, index: number) => void;
clickedLinks: Set<string>;
onResize: (index: number, delta: number) => void;
isFocused: boolean;
}) => {
const paneRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (isFocused && paneRef.current) {
paneRef.current.focus();
paneRef.current.scrollIntoView({ behavior: 'smooth', inline: 'start' });
}
}, [isFocused]);

return (
<div
ref={paneRef}
className={`pane-container relative flex-none h-full ${isFocused ? 'focused' : ''}`}
style={{ width: pane.width }}
tabIndex={0}
>
<div className="h-full border-r border-gray-200 overflow-y-auto">
<div className="flex justify-between items-center p-2 bg-gray-100 sticky top-0 z-10">
<h2 className="text-sm font-bold truncate text-black">{pane.title}</h2>
<button
onClick={() => onClose(index)}
className="p-1 hover:bg-gray-200 rounded-full transition-colors duration-200 text-black"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd" />
</svg>
</button>
</div>
<div
className="wikipedia-content"
onClick={(e) => onClick(e, index)}
dangerouslySetInnerHTML={{ __html: pane.content }}
ref={(node) => {
if (node) {
node.querySelectorAll("a").forEach(a => {
if (clickedLinks.has(a.href)) {
a.classList.add("clicked-link");
}
});
}
}}
/>
</div>
<Resizer onResize={(delta) => onResize(index, delta)} />
</div>
);
});
PaneComponent.displayName = "PaneComponent";

export default PaneComponent;
6 changes: 6 additions & 0 deletions web/src/components/Pane/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default interface Pane {
title: string;
content: string;
isSearchResult: boolean;
width: number;
}
36 changes: 36 additions & 0 deletions web/src/components/SearchBar/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { memo, useState } from "react";

const SearchBar = memo(({ onSearch }: { onSearch: (term: string, isSearchResult: boolean) => void }) => {
const [searchTerm, setSearchTerm] = useState("");

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (searchTerm.trim()) {
onSearch(searchTerm, true);
setSearchTerm("");
}
};

return (
<div className="p-4 bg-gray-100">
<form onSubmit={handleSubmit} className="flex">
<input
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Enter a Wikipedia page title"
className="flex-grow px-4 py-2 text-black border border-gray-300 rounded-l-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
type="submit"
className="px-4 py-2 bg-blue-500 text-white rounded-r-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Search
</button>
</form>
</div>
);
});
SearchBar.displayName = "SearchBar";

export default SearchBar;
Loading

0 comments on commit 4ce9bde

Please sign in to comment.