update crc cards post

This commit is contained in:
Julien Calixte
2022-12-07 09:31:13 +01:00
parent 1f5bff10f2
commit e78c5c6713
3 changed files with 22 additions and 81 deletions

11
components.d.ts vendored
View File

@@ -1,11 +1,8 @@
// generated by unplugin-vue-components // generated by unplugin-vue-components
// We suggest you to commit this file into source control // We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/core/pull/3399 // Read more: https://github.com/vuejs/vue-next/pull/3399
import '@vue/runtime-core'
export {} declare module 'vue' {
declare module '@vue/runtime-core' {
export interface GlobalComponents { export interface GlobalComponents {
AboutMe: typeof import('./src/components/presentation/about-me.vue')['default'] AboutMe: typeof import('./src/components/presentation/about-me.vue')['default']
AppHeader: typeof import('./src/components/app-header.vue')['default'] AppHeader: typeof import('./src/components/app-header.vue')['default']
@@ -16,8 +13,8 @@ declare module '@vue/runtime-core' {
MyBooks: typeof import('./src/components/presentation/my-books.vue')['default'] MyBooks: typeof import('./src/components/presentation/my-books.vue')['default']
MyProjects: typeof import('./src/components/presentation/my-projects.vue')['default'] MyProjects: typeof import('./src/components/presentation/my-projects.vue')['default']
ProductionFlow: typeof import('./src/components/flow/ProductionFlow.vue')['default'] ProductionFlow: typeof import('./src/components/flow/ProductionFlow.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Welcome: typeof import('./src/components/Welcome.vue')['default'] Welcome: typeof import('./src/components/Welcome.vue')['default']
} }
} }
export { }

View File

@@ -122,7 +122,8 @@ code {
} }
blockquote { blockquote {
padding: 2rem; padding: 1.2rem;
margin: 1rem 2rem;
border-radius: 0.3em; border-radius: 0.3em;
background-color: #574b90; background-color: #574b90;
} }

View File

@@ -78,7 +78,7 @@ export const UserBookmarks: FunctionComponent<Props> = ({ user }) => {
}) })
return <div className="user-bookmarks"> return <div className="user-bookmarks">
<Title title={strings['frontoffice.bookmark.user_bookmarks']} /> <Title title={i18n('bookmark.user_bookmarks')} />
{isLoading {isLoading
? <TilesSkeleton animation={tilesAnimation} numberOfTiles={16} /> ? <TilesSkeleton animation={tilesAnimation} numberOfTiles={16} />
: <BookmarkItem : <BookmarkItem
@@ -87,9 +87,8 @@ export const UserBookmarks: FunctionComponent<Props> = ({ user }) => {
/>} />}
<PrimaryButton <PrimaryButton
text={strings['frontoffice.bookmark.all_bookmarks']} text={i18n('bookmark.add_bookmark')}
onClick={() => setShowAddBookmarkModal(true))} onClick={() => setShowAddBookmarkModal(true))}
alt={'strings['frontoffice.bookmark.add_bookmarks']'}
image={<FontAwesomeIcon icon={['fas', 'plus']} color="white" />} image={<FontAwesomeIcon icon={['fas', 'plus']} color="white" />}
/> />
@@ -128,91 +127,35 @@ But hey! We can already note the first responsability on our CRC card.
As we are talking about inputs, I want to know how the props are used. Are they necessary? Are they sufficient? Here we can see that `user` is only used for fetching data: As we are talking about inputs, I want to know how the props are used. Are they necessary? Are they sufficient? Here we can see that `user` is only used for fetching data:
```ts ```ts
... // ...
const userBookmark = await fetch(`/users/${user.id}/bookmarks`, { const userBookmark = await fetch(`/users/${user.id}/bookmarks`, {
... // ...
const newBookmark = await fetch(`/users/${user.id}/bookmarks`, {
// ...
``` ```
Only the `user id` is necessary, why not just give the userId instead of the whole object? Only the `user id` is necessary, why not just give the user id instead of the whole object? That will be our first simplification.
> Here is a classic responsibility leak I frequentely see. Components don't care that user have a `user.address.line1` property when they only want their `id`. > Here is a classic responsibility leak I frequentely see. When you're developing a feature, you have the big picture but `UserBookmarks` and its local knowledge don't care about the user having a `user.address.line1` property.
That will be our first simplification.
```tsx ```tsx
interface Props { interface Props {
userId: number userId: number
} }
export const UserBookmarks: FunctionComponent<Props> = ({ userID }) => { export const UserBookmarks: FunctionComponent<Props> = ({ userId }) => {
const [bookmarks, setBookmarks] = useState<Bookmark[]>([]) // ...
const [showAddBookmarkModal, setShowAddBookmarkModal] = useState(false)
const [isLoading, setIsLoading] = useState(false)
useEffect(() => {
setIsLoading(true)
try {
const userBookmark = await fetch(`/users/${userId}/bookmarks`, { const userBookmark = await fetch(`/users/${userId}/bookmarks`, {
method: 'GET' method: 'GET'
}) })
setBookmarks(userBookmarks) // ...
} catch (error) {
setBookmarks([])
} finally {
setIsLoading(false)
}
}, [])
const addBookmarkToUser = async ({ bookmark }) => {
setIsLoading(true)
try {
const newBookmark = await fetch(`/users/${userId}/bookmarks`, { const newBookmark = await fetch(`/users/${userId}/bookmarks`, {
method: 'POST', method: 'POST',
body: JSON.stringify({ bookmark }) body: JSON.stringify({ bookmark })
}) })
setBookmarks([...bookmarks, newBookmark]) // ...
} catch (error) {
console.warn(error);
} finally {
setIsLoading(false)
}
}
const tilesAnimation = gsap.to({
duration: 0.8,
opacity: 0.35,
yoyo: true,
repeat: -1,
stagger: 0.025,
})
return <div className="user-bookmarks">
<Title title={strings['frontoffice.bookmark.user_bookmarks']} />
{isLoading
? <TilesSkeleton animation={tilesAnimation} numberOfTiles={16} />
: <BookmarkItem
key={bookmark.id}
data={bookmark}
/>}
<PrimaryButton
text={strings['frontoffice.bookmark.all_bookmarks']}
onClick={() => setShowAddBookmarkModal(true))}
alt={'strings['frontoffice.bookmark.add_bookmarks']'}
image={<FontAwesomeIcon icon={['fas', 'plus']} color="white" />}
/>
<AddBookmarkModal
visible={showAddBookmarkModal}
onClose={() => setShowAddBookmarkModal(false)}
bookmarks={bookmarks}
onBookmarkAdd={addBookmarkToUser}
/>
</div>
}
``` ```
## The secret sauce ## The secret sauce
Now comes where we'll definetely challenge how the component does its magic. Now comes where we'll challenge how the component does its magic.