Merge branch 'AW-105-palmistry-points' into 'develop'
AW-105-palmistry-points See merge request witapp/aura-webapp!183
This commit is contained in:
commit
524de968e6
@ -4,10 +4,19 @@ export interface Payload {
|
||||
formData: FormData;
|
||||
}
|
||||
|
||||
export type Response = IPalmistryLine[];
|
||||
export type Response = {
|
||||
fingers: IPalmistryFinger[];
|
||||
lines: IPalmistryLine[];
|
||||
};
|
||||
|
||||
export interface IPalmistryFinger {
|
||||
name: string;
|
||||
point: IPalmistryPoint;
|
||||
}
|
||||
|
||||
export interface IPalmistryLine {
|
||||
line: string;
|
||||
name: string;
|
||||
line: number;
|
||||
points: IPalmistryPoint[];
|
||||
}
|
||||
|
||||
|
||||
@ -51,26 +51,6 @@
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
.scanned-photo__finger-point_thumb {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.scanned-photo__finger-point_index {
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
.scanned-photo__finger-point_middle {
|
||||
animation-delay: 2s;
|
||||
}
|
||||
|
||||
.scanned-photo__finger-point_ring {
|
||||
animation-delay: 3s;
|
||||
}
|
||||
|
||||
.scanned-photo__finger-point_little {
|
||||
animation-delay: 4s;
|
||||
}
|
||||
|
||||
.scanned-photo__line {
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
import { IPalmistryLine, IPalmistryPoint } from "@/api/resources/Palmistry";
|
||||
import {
|
||||
IPalmistryFinger,
|
||||
IPalmistryLine,
|
||||
IPalmistryPoint,
|
||||
} from "@/api/resources/Palmistry";
|
||||
import "./scanned-photo.css";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
@ -7,13 +11,15 @@ type Props = {
|
||||
small: boolean;
|
||||
displayLines: boolean;
|
||||
lines: IPalmistryLine[];
|
||||
lineChangeDelay: number;
|
||||
fingers: IPalmistryFinger[];
|
||||
drawElementChangeDelay: number;
|
||||
startDelay: number;
|
||||
drawElements: Array<IPalmistryLine | IPalmistryFinger>;
|
||||
};
|
||||
|
||||
export default function StepScanPhoto(props: Props) {
|
||||
const className = ["scanned-photo"];
|
||||
const { lines, lineChangeDelay } = props;
|
||||
const { lines, drawElementChangeDelay, fingers, drawElements } = props;
|
||||
const imageRef = useRef<HTMLImageElement>(null);
|
||||
const linesRef = useRef<SVGPathElement[]>([]);
|
||||
const [isImageLoaded, setIsImageLoaded] = useState(false);
|
||||
@ -51,7 +57,7 @@ export default function StepScanPhoto(props: Props) {
|
||||
};
|
||||
|
||||
// const getAnimationDelayOfLine = (index: number) => {
|
||||
// return `${lineChangeDelay * index + startDelay}ms`;
|
||||
// return `${drawElementChangeDelay * index + startDelay}ms`;
|
||||
// };
|
||||
|
||||
return (
|
||||
@ -65,7 +71,9 @@ export default function StepScanPhoto(props: Props) {
|
||||
<div
|
||||
className="scanned-photo__stick"
|
||||
style={{
|
||||
animationDelay: `${lineChangeDelay * lines.length + 2500}ms`,
|
||||
animationDelay: `${
|
||||
drawElementChangeDelay * drawElements?.length + 2500
|
||||
}ms`,
|
||||
maxWidth: `${imageWidth}px`,
|
||||
}}
|
||||
/>
|
||||
@ -84,112 +92,52 @@ export default function StepScanPhoto(props: Props) {
|
||||
viewBox={`0 0 ${imageWidth} ${imageHeight}`}
|
||||
className="scanned-photo__svg-objects"
|
||||
>
|
||||
{/* <svg x="235" y="211" height="24px" width="24px">
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="11"
|
||||
fill="white"
|
||||
opacity="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_thumb"
|
||||
/>
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="5"
|
||||
fill="#066FDE"
|
||||
stroke="white"
|
||||
strokeWidth="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_thumb"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<svg x="172" y="38" height="24px" width="24px">
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="11"
|
||||
fill="white"
|
||||
opacity="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_index"
|
||||
/>
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="5"
|
||||
fill="#066FDE"
|
||||
stroke="white"
|
||||
strokeWidth="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_index"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<svg x="125" y="10" height="24px" width="24px">
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="11"
|
||||
fill="white"
|
||||
opacity="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_middle"
|
||||
/>
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="5"
|
||||
fill="#066FDE"
|
||||
stroke="white"
|
||||
strokeWidth="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_middle"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<svg x="81" y="41" height="24px" width="24px">
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="11"
|
||||
fill="white"
|
||||
opacity="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_ring"
|
||||
/>
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="5"
|
||||
fill="#066FDE"
|
||||
stroke="white"
|
||||
strokeWidth="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_ring"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<svg x="32" y="113" height="24px" width="24px">
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="11"
|
||||
fill="white"
|
||||
opacity="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_little"
|
||||
/>
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="5"
|
||||
fill="#066FDE"
|
||||
stroke="white"
|
||||
strokeWidth="0.3"
|
||||
className="scanned-photo__finger-point scanned-photo__finger-point_little"
|
||||
/>
|
||||
</svg> */}
|
||||
{fingers.map((finger, index) => {
|
||||
return (
|
||||
<svg
|
||||
x={finger.point.x * imageWidth - 12}
|
||||
y={finger.point.y * imageHeight - 12}
|
||||
height="24px"
|
||||
width="24px"
|
||||
key={index}
|
||||
>
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="11"
|
||||
fill="white"
|
||||
opacity="0.3"
|
||||
className="scanned-photo__finger-point"
|
||||
style={{
|
||||
animationDelay: `${
|
||||
drawElementChangeDelay * (index + 1)
|
||||
}ms`,
|
||||
}}
|
||||
/>
|
||||
<circle
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
r="5"
|
||||
fill="#066FDE"
|
||||
stroke="white"
|
||||
strokeWidth="0.3"
|
||||
className="scanned-photo__finger-point"
|
||||
style={{
|
||||
animationDelay: `${
|
||||
drawElementChangeDelay * (index + 1)
|
||||
}ms`,
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
})}
|
||||
|
||||
{props.displayLines && (
|
||||
<>
|
||||
{lines.map((line, index) => (
|
||||
<path
|
||||
key={index}
|
||||
className={`scanned-photo__line scanned-photo__line_${line?.line}`}
|
||||
className={`scanned-photo__line scanned-photo__line_${line?.name}`}
|
||||
d={getCoordinatesString(line?.points)}
|
||||
ref={(el) =>
|
||||
(linesRef.current[index] = el as SVGPathElement)
|
||||
@ -199,30 +147,12 @@ export default function StepScanPhoto(props: Props) {
|
||||
getLineLength(linesRef.current[index]) || 500,
|
||||
strokeDashoffset:
|
||||
getLineLength(linesRef.current[index]) || 500,
|
||||
animationDelay: `${lineChangeDelay * (index + 1)}ms`,
|
||||
animationDelay: `${
|
||||
drawElementChangeDelay * (index + 1)
|
||||
}ms`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{/* <path
|
||||
className={`scanned-photo__line scanned-photo__line_heart`}
|
||||
d="M 95 334 L 99 330 L 104 327 L 109 323 L 113 319 L 118 315 L 123 311 L 128 308 L 132 304 L 137 301 L 142 298 L 146 296 L 151 293 L 156 291 L 160 289 L 165 287 L 170 286 L 174 284 L 179 283 L 184 283 L 189 282 L 193 282 L 198 283 L 203 284 L 207 285"
|
||||
style={{ strokeDasharray: 128.14, strokeDashoffset: 128.14 }}
|
||||
/> */}
|
||||
{/* <path
|
||||
className="scanned-photo__line scanned-photo__line_life"
|
||||
d="M 205 283 L 193 291 L 181 299 L 170 306 L 160 314 L 153 322 L 147 329 L 143 337 L 139 345 L 136 352 L 133 360 L 130 368 L 128 376 L 126 383 L 125 391 L 125 399 L 126 406 L 128 414 L 132 422 L 137 429 L 143 437 L 149 445 L 156 452"
|
||||
style={{ strokeDasharray: 211.483, strokeDashoffset: 211.483 }}
|
||||
/>
|
||||
<path
|
||||
className="scanned-photo__line scanned-photo__line_head"
|
||||
d="M 24 316 L 29 316 L 34 315 L 38 315 L 43 314 L 48 313 L 52 312 L 57 312 L 62 311 L 67 310 L 71 309 L 76 307 L 81 305 L 85 303 L 90 301 L 95 298 L 99 296 L 104 294 L 109 292 L 113 289 L 118 287 L 123 284 L 128 280 L 132 276 L 137 271 L 142 265"
|
||||
style={{ strokeDasharray: 132.6, strokeDashoffset: 132.6 }}
|
||||
/>
|
||||
<path
|
||||
className="scanned-photo__line scanned-photo__line_fate"
|
||||
d="M 134 260 L 129 299 L 125 306 L 122 314 L 120 322 L 118 329 L 116 337 L 115 345 L 114 352"
|
||||
style={{ strokeDasharray: 94.8313, strokeDashoffset: 94.8313 }}
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
</svg>
|
||||
@ -232,13 +162,15 @@ export default function StepScanPhoto(props: Props) {
|
||||
<div
|
||||
className="scanned-photo__decoration"
|
||||
style={{
|
||||
animationDelay: `${lineChangeDelay * lines?.length}ms`,
|
||||
animationDelay: `${drawElementChangeDelay * drawElements?.length}ms`,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="scanned-photo__decoration__corners"
|
||||
style={{
|
||||
animationDelay: `${lineChangeDelay * lines?.length + 1500}ms`,
|
||||
animationDelay: `${
|
||||
drawElementChangeDelay * drawElements?.length + 1500
|
||||
}ms`,
|
||||
}}
|
||||
>
|
||||
<div className="scanned-photo__decoration__light-blue-circle" />
|
||||
@ -270,7 +202,9 @@ export default function StepScanPhoto(props: Props) {
|
||||
>
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
dur={`${lineChangeDelay * lines?.length + 3000}ms`}
|
||||
dur={`${
|
||||
drawElementChangeDelay * drawElements?.length + 3000
|
||||
}ms`}
|
||||
type="rotate"
|
||||
from="0 110 110"
|
||||
to="360 110 110"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
import { Step } from "@/hooks/palmistry/use-steps";
|
||||
import useSteps from "@/hooks/palmistry/use-steps";
|
||||
@ -7,8 +7,9 @@ import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import routes from "@/routes";
|
||||
import { IPalmistryLine } from "@/api/resources/Palmistry";
|
||||
|
||||
const lineChangeDelay = 1500;
|
||||
const drawElementChangeDelay = 1500;
|
||||
const startDelay = 500;
|
||||
// const goNextDelay = 12000;
|
||||
|
||||
@ -19,46 +20,61 @@ export default function StepScanPhoto() {
|
||||
const storedPhoto = steps.getStoredValue(Step.Upload);
|
||||
|
||||
const lines = useSelector(selectors.selectPalmistryLines);
|
||||
const fingers = useSelector(selectors.selectPalmistryFingers);
|
||||
const drawElements = useMemo(() => [...fingers, ...lines], [fingers, lines]);
|
||||
|
||||
const [currentElementIndex, setCurrentElementIndex] = useState(0);
|
||||
const [smallPhotoState, setSmallPhotoState] = useState(false);
|
||||
const [title, setTitle] = useState("");
|
||||
const [shouldDisplayPalmLines, setShouldDisplayPalmLines] = useState(false);
|
||||
const changeTitleTimeOut = useRef<NodeJS.Timeout>();
|
||||
|
||||
const prevElementIndex = useRef<number | null>(null);
|
||||
|
||||
const goNextElement = (delay: number) => {
|
||||
setTimeout(() => {
|
||||
setTitle(lines[currentElementIndex]?.line);
|
||||
changeTitleTimeOut.current = setTimeout(() => {
|
||||
setTitle(drawElements[currentElementIndex]?.name);
|
||||
setCurrentElementIndex((prevState) => prevState + 1);
|
||||
}, delay);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!lines.length) {
|
||||
if (!drawElements.length) {
|
||||
return navigate(routes.client.palmistryUpload());
|
||||
}
|
||||
}, [lines, navigate]);
|
||||
}, [drawElements, navigate]);
|
||||
|
||||
useEffect(() => {
|
||||
// if (currentElementIndex === 0) {
|
||||
// new Promise((resolve) => setTimeout(resolve, startDelay));
|
||||
// }
|
||||
if (
|
||||
currentElementIndex < lines?.length &&
|
||||
currentElementIndex < drawElements?.length &&
|
||||
currentElementIndex !== prevElementIndex.current
|
||||
) {
|
||||
prevElementIndex.current = currentElementIndex;
|
||||
goNextElement(lineChangeDelay);
|
||||
setShouldDisplayPalmLines(lines?.includes(lines[currentElementIndex]));
|
||||
goNextElement(drawElementChangeDelay);
|
||||
setShouldDisplayPalmLines(
|
||||
lines?.includes(drawElements[currentElementIndex] as IPalmistryLine)
|
||||
);
|
||||
}
|
||||
|
||||
if (currentElementIndex >= lines?.length) {
|
||||
setTimeout(() => {
|
||||
if (currentElementIndex >= drawElements?.length) {
|
||||
const toSmallTimeOut = setTimeout(() => {
|
||||
setSmallPhotoState(true);
|
||||
}, lineChangeDelay);
|
||||
setTimeout(steps.goNext, lineChangeDelay * lines.length + 8000);
|
||||
}, drawElementChangeDelay);
|
||||
const goNextTimeOut = setTimeout(
|
||||
steps.goNext,
|
||||
drawElementChangeDelay * drawElements.length + 8000
|
||||
);
|
||||
return () => {
|
||||
clearTimeout(toSmallTimeOut);
|
||||
clearTimeout(goNextTimeOut);
|
||||
};
|
||||
}
|
||||
return () => {
|
||||
if (changeTitleTimeOut.current) clearTimeout(changeTitleTimeOut.current);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentElementIndex]);
|
||||
|
||||
@ -74,25 +90,29 @@ export default function StepScanPhoto() {
|
||||
<h2
|
||||
className="palmistry-container__title"
|
||||
style={{
|
||||
animationDelay: `${lineChangeDelay * lines.length}ms`,
|
||||
animationDelay: `${drawElementChangeDelay * drawElements.length}ms`,
|
||||
animationDuration: `${drawElementChangeDelay}ms`,
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</h2>
|
||||
{/* <pre>{JSON.stringify(lines, null, 2)}</pre> */}
|
||||
<ScannedPhoto
|
||||
photo={storedPhoto}
|
||||
small={smallPhotoState}
|
||||
lineChangeDelay={lineChangeDelay}
|
||||
drawElementChangeDelay={drawElementChangeDelay}
|
||||
startDelay={startDelay}
|
||||
displayLines={shouldDisplayPalmLines}
|
||||
lines={lines}
|
||||
fingers={fingers}
|
||||
drawElements={drawElements}
|
||||
/>
|
||||
|
||||
<h2
|
||||
className="palmistry-container__waiting-title"
|
||||
style={{
|
||||
animationDelay: `${lineChangeDelay * lines.length + 2500}ms`,
|
||||
animationDelay: `${
|
||||
drawElementChangeDelay * drawElements.length + 2500
|
||||
}ms`,
|
||||
}}
|
||||
>
|
||||
We are putting together a comprehensive Palmistry Reading just for you!
|
||||
@ -101,7 +121,9 @@ export default function StepScanPhoto() {
|
||||
<h3
|
||||
className="palmistry-container__waiting-description"
|
||||
style={{
|
||||
animationDelay: `${lineChangeDelay * lines.length + 3000}ms`,
|
||||
animationDelay: `${
|
||||
drawElementChangeDelay * drawElements.length + 3000
|
||||
}ms`,
|
||||
}}
|
||||
>
|
||||
Wow, looks like there is a lot we can tell about your ambitious and
|
||||
|
||||
@ -41,7 +41,12 @@ export default function StepUpload(props: Props) {
|
||||
formData.append("file", file);
|
||||
const result = await api.getPalmistryLines({ formData });
|
||||
|
||||
dispatch(actions.palmistry.update({ lines: result }));
|
||||
dispatch(
|
||||
actions.palmistry.update({
|
||||
lines: result?.lines,
|
||||
fingers: result?.fingers,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const onSelectFile = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
||||
@ -264,7 +264,7 @@ const routes = {
|
||||
[apiHost, prefix, "ai", "assistants", chatId, "chats.json"].join("/"),
|
||||
// Palmistry
|
||||
getPalmistryLines: () =>
|
||||
["https://api.aura.witapps.us", "palmistry", "lines"].join("/"),
|
||||
[dApiHost, dApiPrefix, "palmistry", "lines"].join("/"),
|
||||
|
||||
// Paywall
|
||||
getPaywallByPlacementKey: (placementKey: EPlacementKeys) =>
|
||||
|
||||
@ -67,6 +67,7 @@ import {
|
||||
} from "./userCallbacks";
|
||||
import palmistry, {
|
||||
actions as palmistryActions,
|
||||
selectPalmistryFingers,
|
||||
selectPalmistryLines,
|
||||
} from "./palmistry";
|
||||
import { selectPaywallsIsMustUpdate, selectPaywalls } from "./paywalls";
|
||||
@ -121,6 +122,7 @@ export const selectors = {
|
||||
selectIsForceShortPath,
|
||||
selectOpenAiToken,
|
||||
selectPalmistryLines,
|
||||
selectPalmistryFingers,
|
||||
selectPaywalls,
|
||||
selectPaywallsIsMustUpdate,
|
||||
selectPrivacyPolicy,
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
import { IPalmistryLine } from "@/api/resources/Palmistry";
|
||||
import { IPalmistryFinger, IPalmistryLine } from "@/api/resources/Palmistry";
|
||||
import { createSlice, createSelector } from "@reduxjs/toolkit";
|
||||
import type { PayloadAction } from "@reduxjs/toolkit";
|
||||
|
||||
interface IPalmistry {
|
||||
lines: IPalmistryLine[];
|
||||
fingers: IPalmistryFinger[];
|
||||
}
|
||||
|
||||
const initialState: IPalmistry = {
|
||||
lines: [],
|
||||
fingers: []
|
||||
};
|
||||
|
||||
const palmistrySlice = createSlice({
|
||||
@ -26,4 +28,8 @@ export const selectPalmistryLines = createSelector(
|
||||
(state: { palmistry: IPalmistry }) => state.palmistry.lines,
|
||||
(palmistry) => palmistry
|
||||
);
|
||||
export const selectPalmistryFingers = createSelector(
|
||||
(state: { palmistry: IPalmistry }) => state.palmistry.fingers,
|
||||
(palmistry) => palmistry
|
||||
);
|
||||
export default palmistrySlice.reducer;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user