Make styled part card for displaying many in a list

This commit is contained in:
Kurt Hutten
2020-11-08 11:25:42 +11:00
parent 59f65523dc
commit 012ab05c00
7 changed files with 42 additions and 115 deletions

View File

@@ -12,7 +12,7 @@ import { Router, Route, Private } from '@redwoodjs/router'
const Routes = () => { const Routes = () => {
return ( return (
<Router> <Router>
<Route path="/" page={HomePage} name="home" /> <Route path="/" page={PartsPage} name="home" />
{/* <Route path="/blah/*" page={PartsPage} name="home" /> */} {/* <Route path="/blah/*" page={PartsPage} name="home" /> */}
<Route notfound page={NotFoundPage} /> <Route notfound page={NotFoundPage} />
@@ -35,7 +35,6 @@ const Routes = () => {
<Route path="/parts/new" page={NewPartPage} name="newPart" /> <Route path="/parts/new" page={NewPartPage} name="newPart" />
<Route path="/parts/{id}/edit" page={EditPartPage} name="editPart" /> <Route path="/parts/{id}/edit" page={EditPartPage} name="editPart" />
<Route path="/parts/{id}" page={PartPage} name="part" /> <Route path="/parts/{id}" page={PartPage} name="part" />
<Route path="/parts" page={PartsPage} name="parts" />
<Route path="/comments/new" page={NewCommentPage} name="newComment" /> <Route path="/comments/new" page={NewCommentPage} name="newComment" />
<Route path="/comments/{id}/edit" page={EditCommentPage} name="editComment" /> <Route path="/comments/{id}/edit" page={EditCommentPage} name="editComment" />
<Route path="/comments/{id}" page={CommentPage} name="comment" /> <Route path="/comments/{id}" page={CommentPage} name="comment" />

View File

@@ -65,7 +65,7 @@ export default function ImageUploader({
{isEditable && <input {...getInputProps()} />} {isEditable && <input {...getInputProps()} />}
{(cloudinaryId || !isEditable) && <div className="relative overflow-hidden w-full h-full"> {(cloudinaryId || !isEditable) && <div className="relative overflow-hidden w-full h-full">
<CloudinaryImage <CloudinaryImage
className="object-cover w-full h-full rounded shadow overflow-hidden" className="object-cover w-full h-full shadow overflow-hidden"
cloudName="irevdev" cloudName="irevdev"
publicId={cloudinaryId || 'CadHub/eia1kwru54g2kf02s2xx'} publicId={cloudinaryId || 'CadHub/eia1kwru54g2kf02s2xx'}
width={width} width={width}

View File

@@ -45,7 +45,7 @@ const PartProfile = ({userPart, isEditable, onSave, loading, error}) => {
className="rounded-half rounded-br-lg shadow-md border-2 border-gray-200 border-solid" className="rounded-half rounded-br-lg shadow-md border-2 border-gray-200 border-solid"
onImageUpload={() => {}} onImageUpload={() => {}}
aspectRatio={1} aspectRatio={1}
imageUrl={userPart.image === 'abc' ? '': userPart.image} imageUrl={userPart.image}
width={300} width={300}
/> />
<h4 className="text-indigo-800 text-xl underline text-right py-4">{userPart?.name}</h4> <h4 className="text-indigo-800 text-xl underline text-right py-4">{userPart?.name}</h4>

View File

@@ -1,112 +1,39 @@
import { useMutation, useFlash } from '@redwoodjs/web' import { useMutation, useFlash } from '@redwoodjs/web'
import { Link, routes } from '@redwoodjs/router' import { Link, routes } from '@redwoodjs/router'
const DELETE_PART_MUTATION = gql` import ImageUploader from 'src/components/ImageUploader'
mutation DeletePartMutation($id: String!) {
deletePart(id: $id) {
id
}
}
`
const MAX_STRING_LENGTH = 150
const truncate = (text) => {
let output = text
if (text && text.length > MAX_STRING_LENGTH) {
output = output.substring(0, MAX_STRING_LENGTH) + '...'
}
return output
}
const jsonTruncate = (obj) => {
return truncate(JSON.stringify(obj, null, 2))
}
const timeTag = (datetime) => {
return (
<time dateTime={datetime} title={datetime}>
{new Date(datetime).toUTCString()}
</time>
)
}
const checkboxInputTag = (checked) => {
return <input type="checkbox" checked={checked} disabled />
}
const PartsList = ({ parts }) => { const PartsList = ({ parts }) => {
const { addMessage } = useFlash()
const [deletePart] = useMutation(DELETE_PART_MUTATION, {
onCompleted: () => {
addMessage('Part deleted.', { classes: 'rw-flash-success' })
},
})
const onDeleteClick = (id) => {
if (confirm('Are you sure you want to delete part ' + id + '?')) {
deletePart({ variables: { id }, refetchQueries: ['PARTS'] })
}
}
return ( return (
<div className="rw-segment rw-table-wrapper-responsive"> <section className="max-w-6xl mx-auto mt-20">
<table className="rw-table"> <ul className="grid gap-8 items-center mx-4" style={{gridTemplateColumns: 'repeat(auto-fit, minmax(16rem, 1fr))'}}>
<thead> {parts.map(({title, mainImage, user}) => (
<tr> <li className="rounded-lg overflow-hidden shadow-md hover:shadow-lg mx-px transform hover:-translate-y-px transition-all duration-150" key={`${user?.userName}--${title}`}><button className="w-full">
<th>Id</th> <div className="flex items-center p-2 bg-gray-200 border-gray-300 rounded-t-lg border-t border-l border-r">
<th>Title</th> <div className="w-8 h-8 overflow-hidden rounded-full border border-indigo-300 shadow max-w-xs">
<th>Description</th> <ImageUploader
<th>Code</th> className=""
<th>Main image</th> onImageUpload={() => {}}
<th>Created at</th> aspectRatio={1}
<th>Updated at</th> imageUrl={user?.image}
<th>User id</th> width={50}
<th>&nbsp;</th> />
</tr> </div>
</thead> <span className="font-ropa-sans ml-3 text-lg text-indigo-900">{title}</span>
<tbody> </div>
{parts.map((part) => ( <div className="w-full overflow-hidden relative">
<tr key={part.id}> <ImageUploader
<td>{truncate(part.id)}</td> className=""
<td>{truncate(part.title)}</td> onImageUpload={() => {}}
<td>{truncate(part.description)}</td> aspectRatio={1.4}
<td>{truncate(part.code)}</td> imageUrl={mainImage}
<td>{truncate(part.mainImage)}</td> width={700}
<td>{timeTag(part.createdAt)}</td> />
<td>{timeTag(part.updatedAt)}</td> <div className="absolute inset-0" style={{background: 'linear-gradient(19.04deg, rgba(62, 44, 118, 0.46) 10.52%, rgba(60, 54, 107, 0) 40.02%)'}} />
<td>{truncate(part.userId)}</td> </div>
<td> </button></li>
<nav className="rw-table-actions"> ))}
<Link </ul>
to={routes.part({ id: part.id })} </section>
title={'Show part ' + part.id + ' detail'}
className="rw-button rw-button-small"
>
Show
</Link>
<Link
to={routes.editPart({ id: part.id })}
title={'Edit part ' + part.id}
className="rw-button rw-button-small rw-button-blue"
>
Edit
</Link>
<a
href="#"
title={'Delete part ' + part.id}
className="rw-button rw-button-small rw-button-red"
onClick={() => onDeleteClick(part.id)}
>
Delete
</a>
</nav>
</td>
</tr>
))}
</tbody>
</table>
</div>
) )
} }

View File

@@ -7,12 +7,13 @@ export const QUERY = gql`
parts { parts {
id id
title title
description
code
mainImage mainImage
createdAt createdAt
updatedAt updatedAt
userId user {
image
userName
}
} }
} }
` `

View File

@@ -25,7 +25,7 @@ const UserProfile = ({user, isEditable, loading, onSave, error}) => {
const editableTextFields = {userName, name} const editableTextFields = {userName, name}
return ( return (
<> <>
<div className="max-w-2xl mx-auto mt-20 "> <section className="max-w-2xl mx-auto mt-20 ">
<div className="flex" > <div className="flex" >
<div className="w-40 flex-shrink-0"> <div className="w-40 flex-shrink-0">
<ImageUploader <ImageUploader
@@ -36,7 +36,7 @@ const UserProfile = ({user, isEditable, loading, onSave, error}) => {
})} })}
aspectRatio={1} aspectRatio={1}
isEditable={isEditable} isEditable={isEditable}
imageUrl={user.image === 'abc' ? '': user.image} imageUrl={user.image}
width={300} width={300}
/> />
</div> </div>
@@ -66,7 +66,7 @@ const UserProfile = ({user, isEditable, loading, onSave, error}) => {
/> />
</div> </div>
</div> </div>
</div> </section>
</> </>
) )
} }

View File

@@ -57,7 +57,7 @@ const MainLayout = ({ children }) => {
className="rounded-full object-cover" className="rounded-full object-cover"
onImageUpload={() => {}} onImageUpload={() => {}}
aspectRatio={1} aspectRatio={1}
imageUrl={data?.user?.image === 'abc' ? '': data?.user?.image} imageUrl={data?.user?.image}
width={80} width={80}
/>} />}
</a> </a>