Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Krealle committed Dec 17, 2023
0 parents commit 7d3325c
Show file tree
Hide file tree
Showing 93 changed files with 20,611 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
WCL_CLIENT_ID=
WCL_CLIENT_SECRET=
REDIRECT_URL=
3 changes: 3 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
WCL_CLIENT_ID=
WCL_CLIENT_SECRET=
REDIRECT_URL=
84 changes: 84 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* This is intended to be a basic starting point for linting in your app.
* It relies on recommended configs out of the box for simplicity, but you can
* and should modify this configuration to best suit your team's needs.
*/

/** @type {import('eslint').Linter.Config} */
module.exports = {
root: true,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
env: {
browser: true,
commonjs: true,
es6: true,
},

// Base config
extends: ["eslint:recommended"],

overrides: [
// React
{
files: ["**/*.{js,jsx,ts,tsx}"],
plugins: ["react", "jsx-a11y"],
extends: [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended",
],
settings: {
react: {
version: "detect",
},
formComponents: ["Form"],
linkComponents: [
{ name: "Link", linkAttribute: "to" },
{ name: "NavLink", linkAttribute: "to" },
],
},
},

// Typescript
{
files: ["**/*.{ts,tsx}"],
plugins: ["@typescript-eslint", "import"],
parser: "@typescript-eslint/parser",
settings: {
"import/internal-regex": "^~/",
"import/resolver": {
node: {
extensions: [".ts", ".tsx"],
},
typescript: {
alwaysTryTypes: true,
},
},
},
rules: {
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-explicit-any": "warn",
},
extends: [
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
],
},

// Node
{
files: [".eslintrc.js"],
env: {
node: true,
},
},
],
};
33 changes: 33 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*


node_modules
dist
dist-ssr
/.cache
/build
/public/build
*.local


# env
.env
.env.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Welcome to Remix!

- [Remix Docs](https://remix.run/docs)

## Development

From your terminal:

```sh
npm run dev
```

This starts your app in development mode, rebuilding assets on file changes.

## Deployment

First, build your app for production:

```sh
npm run build
```

Then run the app in production mode:

```sh
npm start
```

Now you'll need to pick a host to deploy it to.

### DIY

If you're familiar with deploying node applications, the built-in Remix app server is production-ready.

Make sure to deploy the output of `remix build`

- `build/`
- `public/build/`
34 changes: 34 additions & 0 deletions app/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
function Footer() {
return (
<div className="footer">
<footer>
<small>
<span>
All data is retrieved from&nbsp;
<a
href="https://warcraftlogs.com"
target="_blank"
rel="noopener noreferrer"
>
Warcraft Logs
</a>
.
</span>
<span>
Bear Emotes from&nbsp;
<a
href="https://yilinzc.carrd.co/"
target="_blank"
rel="noopener noreferrer"
>
yilinzc
</a>
.
</span>
</small>
</footer>
</div>
);
}

export default Footer;
26 changes: 26 additions & 0 deletions app/components/WCLAuthorization.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const WCLAuthorization: React.FC = () => {
const handleAuthorization = async () => {
try {
const response = await fetch("/api/authorize", {
method: "POST",
});

if (response.ok) {
const result = await response.json();
console.log("Success:", result.message);
} else {
const errorResult = await response.json();
console.error("Authorization failed:", errorResult.error);
}
} catch (error) {
console.error("Error during authorization:", error);
}
};

return (
<>
<h2>Warcraft Logs Authorization</h2>
<button onClick={handleAuthorization}>Get WCL Auth</button>
</>
);
};
64 changes: 64 additions & 0 deletions app/components/WCLUrlInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ChangeEvent, FormEvent, useState } from "react";
import "../styles/WCLUrlInput.css";
import { ReportParseError, parseWCLUrl } from "../wcl/gql/util/parseWCLUrl";
import useWCLUrlInputStore from "../zustand/WCLUrlInputStore";
import ErrorBear from "./generic/ErrorBear";
import useStatusStore from "../zustand/statusStore";
import { WCLAuthorization } from "./WCLAuthorization";

export const WCLUrlInput = () => {
const [url, setUrl] = useState<string>("");
const [errorBear, setErrorBear] = useState<ReportParseError | undefined>();

const WCLReport = useWCLUrlInputStore();
const status = useStatusStore();

const handleSubmit = async (event: FormEvent) => {
event.preventDefault();

const { reportCode, error } = parseWCLUrl(url);
if (!reportCode || error) {
if (error) {
setErrorBear(error);
}
return;
}
status.setIsFetching(true);

setErrorBear(undefined);
status.setIsFetching(false);
};

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setUrl(event.target.value);
};

return (
<>
<form onSubmit={handleSubmit} className="flex">
<div className="flex">
<div>
<input
type="text"
placeholder="Enter WCL URL"
className="wclUrlInput"
value={url}
onChange={handleChange}
disabled={status.isFetching}
/>
</div>
<button
type="submit"
disabled={status.isFetching}
className="wclUrlButton"
>
{/* isSubmitting ? "Fetching..." : */ "Fetch Fights"}
</button>
</div>
</form>
{errorBear && <ErrorBear error={errorBear} />}
{!status.hasAuth && <WCLAuthorization />}
{/* {!hasAuth && <HandleUserAuthorization />}*/}
</>
);
};
27 changes: 27 additions & 0 deletions app/components/generic/ErrorBear.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import "../../styles/genericStyling.css";
import {
ReportParseError,
reportParseErrorIconMap,
reportParseErrorMap,
} from "../../wcl/gql/util/parseWCLUrl";

interface ErrorBearProps {
error: ReportParseError;
customMsg?: string;
}

const ErrorBear: React.FC<ErrorBearProps> = ({ error, customMsg }) => (
<div className="error-bear-container">
<img
src={reportParseErrorIconMap[error]}
loading="lazy"
width="48"
height="48"
alt="An error occurred:"
/>
<p>{customMsg ? customMsg : reportParseErrorMap[error]}</p>
</div>
);

export default ErrorBear;
18 changes: 18 additions & 0 deletions app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* By default, Remix will handle hydrating your app on the client for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.client
*/

import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";

startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
Loading

0 comments on commit 7d3325c

Please sign in to comment.