Skip to content

Commit

Permalink
feat: menu dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-cooke committed Nov 18, 2022
1 parent feb0b32 commit 594f2c5
Show file tree
Hide file tree
Showing 59 changed files with 1,577 additions and 224 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ on:
- main

jobs:
test:
uses: './.github/workflows/tests.yml'
secrets: inherit
build:
name: 🐳 Build
needs: test
runs-on: ubuntu-latest
steps:
- name: 🛑 Cancel Previous Runs
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Tests

on: [pull_request]
on:
workflow_call:

jobs:
lint:
Expand Down
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"eslint.workingDirectories": [{ "mode": "auto" }]
}
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dev": "NODE_ENV=development nest start --watch",
"test": "jest --runInBand",
"lint": "eslint src",
"type-check": "tsc -p ./tsconfig.build.json --noEmit",
"docker": "docker buildx build ../../ -f ./Dockerfile -t eu.gcr.io/baggers-367917/api:latest --cache-from type=gha --cache-to type=gha,mode=max --push",
"deploy": "kubectl rollout restart deployment ui && kubectl rollout status deployment ui"
},
Expand Down
5 changes: 1 addition & 4 deletions apps/api/src/portfolios/entities/portfolio.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@ export class PortfolioWithMetrics extends Portfolio {
export class PortfolioSummary extends OmitType(PortfolioWithMetrics, [
'holdings',
'transactions',
]) {
@Field(() => [PopulatedHoldingWithMetrics])
top5Holdings: PopulatedHoldingWithMetrics[];
}
]) {}

@ObjectType('Portfolio')
export class PopulatedPortfolioWithMetrics extends OmitType(
Expand Down
1 change: 0 additions & 1 deletion apps/api/tests/jest/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ jest.mock('@baggers/env', () => ({
setupEnv: () => {
if (!process.env.CI) {
const config = require('dotenv').config().parsed;
console.log(config);

return config;
}
Expand Down
1 change: 0 additions & 1 deletion apps/ui/app/components/Forms/index.ts

This file was deleted.

32 changes: 32 additions & 0 deletions apps/ui/app/components/Navbar/navbar-link.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Link } from '@remix-run/react';
import { NavbarLinkProps } from './types';
import { clsx } from 'clsx';
import { Menu, MenuItem } from '@baggers/ui-components';
import { useState } from 'react';
import { ChevronDown } from 'tabler-icons-react';

export function NavbarLink({ option, active }: NavbarLinkProps) {
const classes = clsx(
Expand All @@ -14,6 +17,35 @@ export function NavbarLink({ option, active }: NavbarLinkProps) {
'hover:opacity-100'
);

const [isMenuOpen, setIsMenuOpen] = useState(false);

console.log(isMenuOpen);

if (option.additionalOptions && typeof document !== 'undefined') {
return (
<div
tabIndex={0}
className={classes}
onMouseEnter={(event) => setIsMenuOpen(true)}
onMouseLeave={(event) => setIsMenuOpen(false)}
>
<span className="flex place-items-center gap-1 ">
{option.label}
<ChevronDown width={16} />
</span>
<Menu open={isMenuOpen} static>
{option.additionalOptions.map((o) => (
<MenuItem key={o.to}>
<Link to={o.to || '/'} tabIndex={-1}>
{o.label}
</Link>
</MenuItem>
))}
</Menu>
</div>
);
}

return (
<Link to={option?.to || '/'} className={classes}>
{option.label}
Expand Down
2 changes: 1 addition & 1 deletion apps/ui/app/components/Navbar/navbar-profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { Form } from '@remix-run/react';
import { useCurrentUser } from '~/hooks/useCurrentUser';
import { Avatar } from '../Avatar/avatar';
import { Avatar } from '../../../../../packages/ui-components/src/lib/avatar/avatar';

export const ProfileButton: React.FC = () => {
const user = useCurrentUser();
Expand Down
2 changes: 1 addition & 1 deletion apps/ui/app/components/Navbar/navbar-search.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SearchInput } from '../Forms';
import { SearchInput } from '@baggers/ui-components';
import { NavbarClip } from './navbar-clip';

export function NavbarSearch() {
Expand Down
1 change: 0 additions & 1 deletion apps/ui/app/components/Navbar/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export function Navbar({ options }: NavbarProps) {
'place-items-center',
'absolute',
'w-full',
'overflow-hidden',
'h-24',
'ml-auto',
'mr-auto'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Portfolio } from '@baggers/graphql-types';
import { PortfolioSummary } from '@baggers/graphql-types';
import { tlsx } from '~/util/clsx';

export type PortfolioCardProps = {
portfolio: Portfolio;
portfolio: PortfolioSummary;
};
export function PortfolioCard({ portfolio }: PortfolioCardProps) {
return (
Expand Down
56 changes: 45 additions & 11 deletions apps/ui/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,50 @@
import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import { RemixBrowser } from '@remix-run/react';
import i18next from 'i18next';
import { startTransition, StrictMode } from 'react';
import { hydrateRoot } from 'react-dom/client';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
import { I18nextProvider, initReactI18next } from 'react-i18next';
import { i18nConfig } from './i18n';
import { getInitialNamespaces } from 'remix-i18next';

function hydrate() {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
i18next
.use(initReactI18next) // Tell i18next to use the react-i18next plugin
.use(LanguageDetector) // Setup a client-side language detector
.use(Backend) // Setup your backend
.init({
// This function detects the namespaces your routes rendered while SSR use
...i18nConfig,
ns: getInitialNamespaces(),
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
detection: {
// Here only enable htmlTag detection, we'll detect the language only
// server-side with remix-i18next, by using the `<html lang>` attribute
// we can communicate to the client the language detected server-side
order: ['htmlTag'],
// Because we only use htmlTag, there's no reason to cache the language
// on the browser, so we disable it
caches: [],
},
})
.then(() => {
// After i18next has been initialized, we can hydrate the app
// We need to wait to ensure translations are loaded before the hydration
// Here wrap RemixBrowser in I18nextProvider from react-i18next
return startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<I18nextProvider i18n={i18next}>
<RemixBrowser />
</I18nextProvider>
</StrictMode>
);
});
});
}

if (window.requestIdleCallback) {
Expand Down
35 changes: 31 additions & 4 deletions apps/ui/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { PassThrough } from 'stream';
import { resolve } from 'node:path';
import type { EntryContext } from '@remix-run/node';
import { Response } from '@remix-run/node';
import { RemixServer } from '@remix-run/react';
import isbot from 'isbot';
import { renderToPipeableStream } from 'react-dom/server';
import { createInstance } from 'i18next';
import { i18next } from './server/i18n.server';
import { I18nextProvider, initReactI18next } from 'react-i18next';
import Backend from 'i18next-fs-backend';
import { i18nConfig } from './i18n';

const ABORT_DELAY = 5000;

Expand Down Expand Up @@ -69,17 +75,38 @@ function handleBotRequest(
});
}

function handleBrowserRequest(
async function handleBrowserRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
let didError = false;
// First, we create a new instance of i18next so every request will have a
// completely unique instance and not share any state
const instance = createInstance();

// Then we could detect locale from the request
const lng = await i18next.getLocale(request);
// And here we detect what namespaces the routes about to render want to use
const ns = i18next.getRouteNamespaces(remixContext);

await instance
.use(initReactI18next) // Tell our instance to use react-i18next
.use(Backend) // Setup our backend
.init({
...i18nConfig, // spread the configuration
lng, // The locale we detected above
ns, // The namespaces the routes about to render wants to use
backend: {
loadPath: resolve('../public/locales/{{lng}}/{{ns}}.json'),
},
});
return new Promise((resolve, reject) => {
let didError = false;

const { pipe, abort } = renderToPipeableStream(
<RemixServer context={remixContext} url={request.url} />,
<I18nextProvider i18n={instance}>
<RemixServer context={remixContext} url={request.url} />
</I18nextProvider>,
{
onShellReady() {
const body = new PassThrough();
Expand Down
7 changes: 6 additions & 1 deletion apps/ui/app/hooks/useNavbarOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ export const useNavbarOptions = (): NavbarOption[] => {
additionalOptions: [
{
key: '/portfolios/created',
label: t('created', 'Created'),
label: t('created_portfolios', 'Created portfolios'),
to: '/portfolios/created',
},
{
key: '/portfolios/following',
label: t('followed_portfolios', 'Followed portfolios'),
to: '/portfolios/following',
},
],
},
{
Expand Down
34 changes: 8 additions & 26 deletions apps/ui/app/routes/portfolios/created.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { PortfoliosCreatedQuery } from '@baggers/sdk/src/generated';
import {
PortfoliosCreatedQuery,
PortfolioSummary,
} from '@baggers/graphql-types';
import {
ActionFunction,
json,
Expand All @@ -12,29 +15,8 @@ import { authenticatedSdk } from '~/server/sdk.server';
import { tlsx } from '~/util/clsx';

export const loader: LoaderFunction = async ({ request }) => {
// const sdk = await authenticatedSdk(request);
// return sdk.portfoliosCreated();

return {
portfoliosCreated: [
{
name: 'Test',
cash: 12482.2323232,
private: true,
owner: {
displayName: 'Daniel Cooke',
},
},
{
name: 'Hello',
cash: 12482.2323232,
private: true,
owner: {
displayName: 'Daniel Cooke',
},
},
],
} as PortfoliosCreatedQuery;
const sdk = await authenticatedSdk(request);
return sdk.portfoliosCreated();
};

export const meta: MetaFunction = () => ({
Expand Down Expand Up @@ -67,7 +49,7 @@ export const action: ActionFunction = async ({ request }) => {
};
export default function CreatedPortfoliosPage() {
const { portfoliosCreated } =
useLoaderData<ReturnType<typeof loader>>();
useLoaderData<PortfoliosCreatedQuery>();

return (
<Form method="post">
Expand All @@ -85,7 +67,7 @@ export default function CreatedPortfoliosPage() {
)}
>
{portfoliosCreated.map((portfolio) => (
<PortfolioCard portfolio={portfolio} />
<PortfolioCard portfolio={portfolio as PortfolioSummary} />
))}
</div>
</Form>
Expand Down
4 changes: 2 additions & 2 deletions apps/ui/app/server/i18n.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export const i18next = new RemixI18Next({
...i18nConfig,
backend: {
loadPath: resolve(
join(__dirname, '../public/locales/{{lng}}/{{ns}}.json')
join(__dirname, '../../public/locales/{{lng}}/{{ns}}.json')
),
},
},
backend: Backend,
backend: Backend as any,
});
Loading

0 comments on commit 594f2c5

Please sign in to comment.