Skip to content

Commit

Permalink
improve UX on the landscape (#38)
Browse files Browse the repository at this point in the history
Partially fixes #37 

* add optional color picker component
* update react query lib
* Lock camera when the create new modal is visible* add translation labels
* Remove redundant Suspense
* Restructure pebble creation form
* remove react-helmet entirely
* fix useFrame  in Pebbles component when labelRef is not loaded
* add extra modals for info and confirmation
* add storyItem component in the Hero modals
* add specific translatable message for non validated pebbles
* add cameraLeapHandle event listener (still todo)
* add infobutton on the pebble tooltip
* add showLanguages flag on StoryItem to delete StoryItemSmall component
* fix className on SrollIcon
* Update overlay.css
* Update modal.css
* add delay in Overlay component
* add action to show modal info
* Update hero.css
* add redirects for netlify
  • Loading branch information
danieleguido authored Jan 18, 2024
1 parent afbe33c commit cf41074
Show file tree
Hide file tree
Showing 27 changed files with 543 additions and 207 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ setupProxy.log

# Local Netlify folder
.netlify
netlify.toml
# netlify.toml
22 changes: 22 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[[redirects]]
force = true
from = "/api/*"
to = "https://memorialshoah.lu/api/:splat"
status = 200

[[redirects]]
force = true
from = "/media/*"
to = "https://memorialshoah.lu/media/:splat"
status = 200

[[redirects]]
force = true
from = "/pagefind/*"
to = "https://memorialshoah.lu/pagefind/:splat"
status = 200

[[redirects]]
from = "/*"
to = "/index.html"
status = 200
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@react-spring/parallax": "^9.4.5",
"@react-three/drei": "9.86.3",
"@react-three/fiber": "8.12.0",
"@tanstack/react-query": "^4.35.7",
"@tanstack/react-query": "^5.17.12",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
Expand Down
12 changes: 10 additions & 2 deletions src/components/Hero/Hero.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { usePebblesStore } from './store'
import { StatusSuccess, useGetJSON } from '../../hooks/data'

import { QueryClient, QueryClientProvider } from 'react-query'
import ModalConfirmation from './ui/ModalConfirmation'
import ModalInfo from './ui/ModalInfo'

const Hero = ({ isMobile }) => {
const { data, status, error } = useGetJSON({
Expand All @@ -39,6 +41,10 @@ const Hero = ({ isMobile }) => {
}

const queryClient = new QueryClient()
const cameraLeapHandle = (e, z1, z2) => {
console.debug('[Hero] Camera@LeapHandle placeholder Z range:', z1, z2)
// @todo this should update the list of the pebbles based on their Z value
}

return (
<QueryClientProvider client={queryClient}>
Expand All @@ -53,14 +59,16 @@ const Hero = ({ isMobile }) => {
<Canvas gl={{ alpha: true, antialias: false, shadows: false }} dpr={2}>
{/* <StatsGl /> */}
{/* <Stats showPanel={0} /> */}
<Camera />
<Camera onLeap={cameraLeapHandle} />
<Scene />
</Canvas>
</div>
<Overlay isMobile={isMobile} />
<div className="hero__modals">
<ModalInfo />
<ModalConfirmation disableEmail />
<ModalDetails stories={data?.results} />
<ModalCreate stories={data?.results} />
<ModalCreate withCarousel stories={data?.results} />
</div>
</div>
</QueryClientProvider>
Expand Down
6 changes: 4 additions & 2 deletions src/components/Hero/components/Camera.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const Camera = () => {

const selectedTarget = usePebblesStore((state) => state.selectedPebble)
const hasStarted = usePebblesStore((state) => state.hasStarted)
const hasCreate = usePebblesStore((state) => state.hasCreate)

const [signedPosition, setSignedPosition] = useState(1)

Expand Down Expand Up @@ -163,8 +164,9 @@ export const Camera = () => {

useSafeFrame((_, delta) => {
if (!cameraRef.current) return

if (hasStarted) {
if (hasCreate) {
cameraForward()
} else if (hasStarted) {
if (selectedTarget) {
cameraToTarget()
} else {
Expand Down
48 changes: 32 additions & 16 deletions src/components/Hero/components/Pebbles.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import './Pebbles.css'

export const Pebbles = memo(({ skyColor, groundColor, renderedTexture }) => {
const { nodes } = useGLTF('/models/models.glb')

const diffuseMap = useTexture('/texture/pebbleColor.png')
const normalMap = useTexture('/texture/pebbleBakedNormalsOBJ.png')

diffuseMap.flipY = false
normalMap.flipY = false

Expand Down Expand Up @@ -97,7 +97,7 @@ const SingleInstance = ({ pebble, filteredPebbles, i }) => {
(event) => {
const data = filteredPebbles[i]
usePebblesStore.getState().setSelected(data)
usePebblesStore.getState().setHasCreate(false)
// usePebblesStore.getState().setHasCreate(false)
usePebblesStore.getState().setHasDetails(true)
usePebblesStore.getState().setHasStarted(true)
event.stopPropagation()
Expand All @@ -106,7 +106,7 @@ const SingleInstance = ({ pebble, filteredPebbles, i }) => {
)

const handlePointerMiss = useCallback(() => {
usePebblesStore.getState().setHasCreate(false)
// usePebblesStore.getState().setHasCreate(false)
usePebblesStore.getState().resetSelected()
usePebblesStore.getState().setHasDetails(false)
}, [])
Expand Down Expand Up @@ -136,6 +136,9 @@ const SingleInstance = ({ pebble, filteredPebbles, i }) => {
const color = new THREE.Color()

useFrame((_, delta) => {
if (!labelRef.current) {
return
}
const hasSelected = usePebblesStore.getState().selectedPebble
if (hasSelected) {
const isSelected = pebble.uid === usePebblesStore.getState().selectedPebble.uid
Expand Down Expand Up @@ -206,23 +209,36 @@ const SingleInstance = ({ pebble, filteredPebbles, i }) => {
>
<div ref={labelRef} className="Pebble__Overlay-label">
<div ref={textRef} className="Pebble__Overlay-text">
{pebble.message ? (
{pebble.status !== 'public' ? (
<p
className="Pebble__message"
className="Pebble__message m-0"
dangerouslySetInnerHTML={{
__html: t('pebbleMessage', { message: pebble.message || '' }),
__html: t('pebbleDraftMessage', {
d: t('dateShort', { date: new Date(pebble.createdAt) }),
}),
}}
/>
) : null}
<div
className="Pebble__createdBy"
dangerouslySetInnerHTML={{
__html: t('pebbleCreatedBy', { createdBy: pebble.createdBy || '' }),
}}
/>
<div className="Pebble__createdAt">
on {t('dateShort', { date: new Date(pebble.createdAt) })}
</div>
) : (
<>
{pebble.message ? (
<p
className="Pebble__message"
dangerouslySetInnerHTML={{
__html: t('pebbleMessage', { message: pebble.message || '' }),
}}
/>
) : null}
<div
className="Pebble__createdBy"
dangerouslySetInnerHTML={{
__html: t('pebbleCreatedBy', { createdBy: pebble.createdBy || '' }),
}}
/>
<div className="Pebble__createdAt">
on {t('dateShort', { date: new Date(pebble.createdAt) })}
</div>
</>
)}
</div>
</div>
</Html>
Expand Down
6 changes: 3 additions & 3 deletions src/components/Hero/hero.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
.hero__canvas-wrapper {
position: absolute;
top: 0;
left: 3rem;
right: 3rem;
bottom: 3rem;
left: 1rem;
right: 1rem;
bottom: 50px;
border-radius: 32px;
overflow: hidden;
}
Expand Down
7 changes: 7 additions & 0 deletions src/components/Hero/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ export const usePebblesStore = create((set, get) => ({
positionX: 0,
positionZ: 0,
},
// confirmation modal hide/show
showConfirmationModal: false,
setShowConfirmationModal: (value) => set({ showConfirmationModal: value }),
// info modal hide/show
showInfoModal: false,
setShowInfoModal: (value) => set({ showInfoModal: value }),
// CAMERA STATES:
cameraPosition: new THREE.Vector3(0, 8, 0),
cameraLookAt: new THREE.Vector3(0, 8, 48),
Expand Down Expand Up @@ -200,6 +206,7 @@ export const usePebblesStore = create((set, get) => ({
position: apiPebble.position,
rotation: apiPebble.rotation,
scale: apiPebble.scale,
status: apiPebble.status,
uid: apiPebble.shortUrl,
createdAt: new Date(apiPebble.createdAt),
createdBy: apiPebble.createdBy,
Expand Down
19 changes: 19 additions & 0 deletions src/components/Hero/ui/ColorPicker.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.ColorPicker {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
}
.ColorPicker .btn {
height: 40px;
width: 40px;
border-radius: 40px;
}

.ColorPicker .btn:hover {
box-shadow: 0 0 0 3px rgba(7, 58, 49, 0.5);
}

.ColorPicker .btn.active {
box-shadow: 0 0 0 3px rgba(7, 58, 49, 0.5);
}
33 changes: 33 additions & 0 deletions src/components/Hero/ui/ColorPicker.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useState } from 'react'
import { PebbleColors } from '../../../constants'
import './ColorPicker.css'
import PropTypes from 'prop-types'

const ColorPicker = ({ options = PebbleColors, className = '', onChange }) => {
const [selectedColorIdx, setSelectedColorIdx] = useState(
Math.round(Math.random() * (options.length - 1)),
)
return (
<div className={`ColorPicker ${className}`}>
{PebbleColors.map((c, i) => (
<button
className={`btn btn-sm ${selectedColorIdx === i ? 'active' : ''}`}
style={{ backgroundColor: c }}
key={c}
onClick={() => {
console.debug('[ColorPicker] @click \n - selected color:', c, '\n - idx:', i)
setSelectedColorIdx(i)
onChange(c, i)
}}
></button>
))}
</div>
)
}
ColorPicker.propTypes = {
options: PropTypes.arrayOf(PropTypes.string),
className: PropTypes.string,
onChange: PropTypes.func.isRequired,
}

export default ColorPicker
Loading

0 comments on commit cf41074

Please sign in to comment.