Make styled part card for displaying many in a list
This commit is contained in:
@@ -12,7 +12,7 @@ import { Router, Route, Private } from '@redwoodjs/router'
|
||||
const Routes = () => {
|
||||
return (
|
||||
<Router>
|
||||
<Route path="/" page={HomePage} name="home" />
|
||||
<Route path="/" page={PartsPage} name="home" />
|
||||
{/* <Route path="/blah/*" page={PartsPage} name="home" /> */}
|
||||
<Route notfound page={NotFoundPage} />
|
||||
|
||||
@@ -35,7 +35,6 @@ const Routes = () => {
|
||||
<Route path="/parts/new" page={NewPartPage} name="newPart" />
|
||||
<Route path="/parts/{id}/edit" page={EditPartPage} name="editPart" />
|
||||
<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/{id}/edit" page={EditCommentPage} name="editComment" />
|
||||
<Route path="/comments/{id}" page={CommentPage} name="comment" />
|
||||
|
||||
@@ -65,7 +65,7 @@ export default function ImageUploader({
|
||||
{isEditable && <input {...getInputProps()} />}
|
||||
{(cloudinaryId || !isEditable) && <div className="relative overflow-hidden w-full h-full">
|
||||
<CloudinaryImage
|
||||
className="object-cover w-full h-full rounded shadow overflow-hidden"
|
||||
className="object-cover w-full h-full shadow overflow-hidden"
|
||||
cloudName="irevdev"
|
||||
publicId={cloudinaryId || 'CadHub/eia1kwru54g2kf02s2xx'}
|
||||
width={width}
|
||||
|
||||
@@ -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"
|
||||
onImageUpload={() => {}}
|
||||
aspectRatio={1}
|
||||
imageUrl={userPart.image === 'abc' ? '': userPart.image}
|
||||
imageUrl={userPart.image}
|
||||
width={300}
|
||||
/>
|
||||
<h4 className="text-indigo-800 text-xl underline text-right py-4">{userPart?.name}</h4>
|
||||
|
||||
@@ -1,112 +1,39 @@
|
||||
import { useMutation, useFlash } from '@redwoodjs/web'
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
|
||||
const DELETE_PART_MUTATION = gql`
|
||||
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 />
|
||||
}
|
||||
|
||||
import ImageUploader from 'src/components/ImageUploader'
|
||||
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 (
|
||||
<div className="rw-segment rw-table-wrapper-responsive">
|
||||
<table className="rw-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Title</th>
|
||||
<th>Description</th>
|
||||
<th>Code</th>
|
||||
<th>Main image</th>
|
||||
<th>Created at</th>
|
||||
<th>Updated at</th>
|
||||
<th>User id</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{parts.map((part) => (
|
||||
<tr key={part.id}>
|
||||
<td>{truncate(part.id)}</td>
|
||||
<td>{truncate(part.title)}</td>
|
||||
<td>{truncate(part.description)}</td>
|
||||
<td>{truncate(part.code)}</td>
|
||||
<td>{truncate(part.mainImage)}</td>
|
||||
<td>{timeTag(part.createdAt)}</td>
|
||||
<td>{timeTag(part.updatedAt)}</td>
|
||||
<td>{truncate(part.userId)}</td>
|
||||
<td>
|
||||
<nav className="rw-table-actions">
|
||||
<Link
|
||||
to={routes.part({ id: part.id })}
|
||||
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>
|
||||
<section className="max-w-6xl mx-auto mt-20">
|
||||
<ul className="grid gap-8 items-center mx-4" style={{gridTemplateColumns: 'repeat(auto-fit, minmax(16rem, 1fr))'}}>
|
||||
{parts.map(({title, mainImage, user}) => (
|
||||
<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">
|
||||
<div className="flex items-center p-2 bg-gray-200 border-gray-300 rounded-t-lg border-t border-l border-r">
|
||||
<div className="w-8 h-8 overflow-hidden rounded-full border border-indigo-300 shadow max-w-xs">
|
||||
<ImageUploader
|
||||
className=""
|
||||
onImageUpload={() => {}}
|
||||
aspectRatio={1}
|
||||
imageUrl={user?.image}
|
||||
width={50}
|
||||
/>
|
||||
</div>
|
||||
<span className="font-ropa-sans ml-3 text-lg text-indigo-900">{title}</span>
|
||||
</div>
|
||||
<div className="w-full overflow-hidden relative">
|
||||
<ImageUploader
|
||||
className=""
|
||||
onImageUpload={() => {}}
|
||||
aspectRatio={1.4}
|
||||
imageUrl={mainImage}
|
||||
width={700}
|
||||
/>
|
||||
<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%)'}} />
|
||||
</div>
|
||||
</button></li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,13 @@ export const QUERY = gql`
|
||||
parts {
|
||||
id
|
||||
title
|
||||
description
|
||||
code
|
||||
mainImage
|
||||
createdAt
|
||||
updatedAt
|
||||
userId
|
||||
user {
|
||||
image
|
||||
userName
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -25,7 +25,7 @@ const UserProfile = ({user, isEditable, loading, onSave, error}) => {
|
||||
const editableTextFields = {userName, name}
|
||||
return (
|
||||
<>
|
||||
<div className="max-w-2xl mx-auto mt-20 ">
|
||||
<section className="max-w-2xl mx-auto mt-20 ">
|
||||
<div className="flex" >
|
||||
<div className="w-40 flex-shrink-0">
|
||||
<ImageUploader
|
||||
@@ -36,7 +36,7 @@ const UserProfile = ({user, isEditable, loading, onSave, error}) => {
|
||||
})}
|
||||
aspectRatio={1}
|
||||
isEditable={isEditable}
|
||||
imageUrl={user.image === 'abc' ? '': user.image}
|
||||
imageUrl={user.image}
|
||||
width={300}
|
||||
/>
|
||||
</div>
|
||||
@@ -66,7 +66,7 @@ const UserProfile = ({user, isEditable, loading, onSave, error}) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ const MainLayout = ({ children }) => {
|
||||
className="rounded-full object-cover"
|
||||
onImageUpload={() => {}}
|
||||
aspectRatio={1}
|
||||
imageUrl={data?.user?.image === 'abc' ? '': data?.user?.image}
|
||||
imageUrl={data?.user?.image}
|
||||
width={80}
|
||||
/>}
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user