Skip to content

Commit

Permalink
chore: update with-react example
Browse files Browse the repository at this point in the history
  • Loading branch information
achamorro-dev committed Nov 29, 2022
1 parent cdf5b6d commit ea5a63d
Show file tree
Hide file tree
Showing 29 changed files with 50,070 additions and 60,202 deletions.
3 changes: 2 additions & 1 deletion examples/with-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"dependencies": {
"@archimedes/arch": "2.2.0-beta.2",
"@archimedes/arch": "2.2.0-beta.3",
"@testing-library/jest-dom": "5.16.4",
"@testing-library/react": "13.3.0",
"@testing-library/user-event": "13.5.0",
Expand All @@ -13,6 +13,7 @@
"@types/react-dom": "18.0.5",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-router-dom": "^6.0.2",
"react-scripts": "5.0.1",
"reflect-metadata": "0.1.13",
"tsyringe": "4.7.0",
Expand Down
38 changes: 0 additions & 38 deletions examples/with-react/src/App.css

This file was deleted.

41 changes: 14 additions & 27 deletions examples/with-react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
import { useEffect, useState } from 'react'
import './App.css'
import { useDi } from './use-di'
import { FooCmd } from './foo-cmd'
import { BarQry } from './bar-qry'
import { QuxCmd } from './qux-cmd'
import { BazQry } from './baz-qry'
import { Route, Routes } from 'react-router-dom'
import styles from './app.module.css'
import { CreateTodo } from './features/todo/ui/create-todo/create-todo'
import { TodoList } from './features/todo/ui/todo-list/todo-list'

function App() {
const [result, setResult] = useState(0)
const [calls, setCalls] = useState(0)

const fooCmd = useDi(FooCmd)
useEffect(() => {
const id = fooCmd.subscribe(() => setCalls(x => x + 1))
return () => fooCmd.unsubscribe(id)
})
const barQry = useDi(BarQry)
const quxCmd = useDi(QuxCmd)
const bazQry = useDi(BazQry)
return (
<div className="App">
<button onClick={() => fooCmd.execute(1)}>Invalidate Bar</button>
<button onClick={() => quxCmd.execute(1)}>Invalidate Baz</button>
<button onClick={() => barQry.execute().then(setResult)}>Bar</button>
<button onClick={() => bazQry.execute().then(setResult)}>Baz</button>
<div>
<div className={styles['toolbar']} role="banner">
<div className={styles['spacer']}></div>
<span>ARCHIMEDES WITH REACT</span>
<div className={styles['spacer']}></div>
</div>

<h2>Result</h2>
<p>{result}</p>
<h2>Bar called</h2>
<p>{calls}</p>
<Routes>
<Route path="/" element={<TodoList />} />
<Route path="/create" element={<CreateTodo />} />
</Routes>
</div>
)
}
Expand Down
17 changes: 17 additions & 0 deletions examples/with-react/src/app.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.spacer {
flex: 1;
}

.toolbar {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 60px;
display: flex;
align-items: center;
background-color: var(--primary-color);
color: white;
font-weight: 600;
font-size: 1.25rem;
}
16 changes: 0 additions & 16 deletions examples/with-react/src/bar-qry.ts

This file was deleted.

11 changes: 0 additions & 11 deletions examples/with-react/src/baz-qry.ts

This file was deleted.

1 change: 0 additions & 1 deletion examples/with-react/src/container.ts

This file was deleted.

7 changes: 7 additions & 0 deletions examples/with-react/src/core/di/container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { container } from 'tsyringe'
import { LocalTodoRepository } from '../../features/todo/infrastructure/local-todo-repository'
import { InjectionTokens } from './injection-tokens'

container.registerSingleton(InjectionTokens.TODO_REPOSITORY, LocalTodoRepository)

export { container }
3 changes: 3 additions & 0 deletions examples/with-react/src/core/di/injection-tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class InjectionTokens {
static TODO_REPOSITORY = Symbol.for('TODO_REPOSITORY')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Command, UseCaseKey } from '@archimedes/arch'
import { inject, injectable } from 'tsyringe'
import { InjectionTokens } from '../../../core/di/injection-tokens'
import type { TodoRepository } from '../domain/todo-repository'

@UseCaseKey('CompleteTodoCmd')
@injectable()
export class CompleteTodoCmd extends Command<{ id: number; isCompleted: boolean }> {
constructor(@inject(InjectionTokens.TODO_REPOSITORY) private readonly todoRepository: TodoRepository) {
super()
}

internalExecute({ id, isCompleted }: { id: number; isCompleted: boolean }): Promise<void> {
return this.todoRepository.update(id, { completed: isCompleted })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Command, UseCaseKey } from '@archimedes/arch'
import { inject, injectable } from 'tsyringe'
import { InjectionTokens } from '../../../core/di/injection-tokens'
import { NewTodo } from '../domain/new-todo'
import type { TodoRepository } from '../domain/todo-repository'

@UseCaseKey('CreateTodoCmd')
@injectable()
export class CreateTodoCmd extends Command<NewTodo> {
constructor(@inject(InjectionTokens.TODO_REPOSITORY) private readonly todoRepository: TodoRepository) {
super()
}

internalExecute(newTodo: NewTodo): Promise<void> {
return this.todoRepository.create(newTodo)
}
}
17 changes: 17 additions & 0 deletions examples/with-react/src/features/todo/application/get-todo-qry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Query, UseCaseKey } from '@archimedes/arch'
import { inject, injectable } from 'tsyringe'
import { InjectionTokens } from '../../../core/di/injection-tokens'
import { Todo } from '../domain/todo'
import type { TodoRepository } from '../domain/todo-repository'

@UseCaseKey('GetTodoQry')
@injectable()
export class GetTodoQry extends Query<Todo | undefined, number> {
constructor(@inject(InjectionTokens.TODO_REPOSITORY) private readonly todoRepository: TodoRepository) {
super()
}

internalExecute(id: number): Promise<Todo | undefined> {
return this.todoRepository.get(id)
}
}
18 changes: 18 additions & 0 deletions examples/with-react/src/features/todo/application/get-todos-qry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { InvalidateCache, Query, UseCaseKey } from '@archimedes/arch'
import { inject, injectable } from 'tsyringe'
import { InjectionTokens } from '../../../core/di/injection-tokens'
import { Todo } from '../domain/todo'
import type { TodoRepository } from '../domain/todo-repository'

@UseCaseKey('GetTodosQry')
@InvalidateCache
@injectable()
export class GetTodosQry extends Query<Todo[]> {
constructor(@inject(InjectionTokens.TODO_REPOSITORY) private readonly todoRepository: TodoRepository) {
super()
}

internalExecute(): Promise<Todo[]> {
return this.todoRepository.getAll()
}
}
3 changes: 3 additions & 0 deletions examples/with-react/src/features/todo/domain/new-todo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Todo } from './todo'

export type NewTodo = Omit<Todo, 'id'>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { NewTodo } from './new-todo'
import { Todo } from './todo'

export interface TodoRepository {
getAll(): Promise<Todo[]>
get(id: number): Promise<Todo | undefined>
create(newTodo: NewTodo): Promise<void>
update(id: number, todo: Partial<Todo>): Promise<void>
}
5 changes: 5 additions & 0 deletions examples/with-react/src/features/todo/domain/todo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface Todo {
id: number
title: string
completed: boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { NewTodo } from '../domain/new-todo'
import { Todo } from '../domain/todo'
import { TodoRepository } from '../domain/todo-repository'
import { injectable } from 'tsyringe'

@injectable()
export class HttpTodoRepository implements TodoRepository {
private static TODO_URL = 'https://jsonplaceholder.typicode.com/todos'
private static TODO_BY_ID_URL = (id: number) => `${HttpTodoRepository.TODO_URL}/${id}`

constructor() {}
async get(id: number): Promise<Todo | undefined> {
const response = await fetch(HttpTodoRepository.TODO_BY_ID_URL(id))
return response.json()
}

async getAll(): Promise<Todo[]> {
const response = await fetch(HttpTodoRepository.TODO_URL)
return response.json()
}

async create(newTodo: NewTodo): Promise<void> {
await fetch(HttpTodoRepository.TODO_URL, { method: 'POST', body: JSON.stringify(newTodo) })
}

async update(id: number, todo: Partial<Todo>): Promise<void> {
await fetch(HttpTodoRepository.TODO_BY_ID_URL(id), { method: 'PATCH', body: JSON.stringify(todo) })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { injectable } from 'tsyringe'
import { NewTodo } from '../domain/new-todo'
import { Todo } from '../domain/todo'
import { TodoRepository } from '../domain/todo-repository'

@injectable()
export class LocalTodoRepository implements TodoRepository {
private readonly todos = new Map<number, Todo>()

async getAll(): Promise<Todo[]> {
return Array.from(this.todos.values())
}

async get(id: number): Promise<Todo | undefined> {
return this.todos.get(id)
}

async create(newTodo: NewTodo): Promise<void> {
const newId = this.todos.size + 1
this.todos.set(newId, { ...newTodo, id: newId })
}

async update(id: number, todo: Partial<Todo>): Promise<void> {
const previousTodo = this.todos.get(id)
this.todos.set(id, { ...previousTodo, ...todo } as Todo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.container {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
margin-top: 72px;
}

.actions {
display: flex;
gap: 1rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { FC, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { useDi } from '../../../../use-di'
import { CreateTodoCmd } from '../../application/create-todo-cmd'
import styles from './create-todo.module.css'

export const CreateTodo: FC = () => {
const [title, setTitle] = useState('')
const createTodoCmd = useDi(CreateTodoCmd)
const navigate = useNavigate()

const saveTodo = async () => {
await createTodoCmd.execute({
title,
completed: false
})
navigate('/')
}

return (
<div className={styles['container']}>
<h2>CREATE TODO</h2>

<label>
Title
<input type="text" value={title} onChange={e => setTitle(e.target.value)} />
</label>

<div className={styles['actions']}>
<Link to="/">Back</Link>
<button onClick={saveTodo}>Save</button>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.container {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
margin-top: 72px;
}

li {
margin-bottom: 1rem;
}

.todo {
border-radius: 4px;
border: 1px solid #eee;
background-color: #fefefe;
padding: 1rem;
display: flex;
cursor: pointer;
font-size: 1rem;
font-weight: normal;
color: #111;
}

.completed {
text-decoration: line-through;
background-color: var(--primary-color);
color: white;
}

.actions {
display: flex;
gap: 1rem;
}
Loading

0 comments on commit ea5a63d

Please sign in to comment.