reza added qr scan

temp
Reza_ashrafi 3 years ago
parent 38286b2a3f
commit ba9fab8a61
  1. BIN
      build.zip
  2. 9
      src/components/Audio/index.js
  3. 1
      src/redux/actions/index.js
  4. 32
      src/redux/actions/qr.js
  5. 4
      src/redux/reducers/index.js
  6. 32
      src/redux/reducers/qr.js
  7. 64
      src/router.js
  8. 4
      src/views/QR/Content/components/Links.js
  9. 4
      src/views/QR/Content/components/PDF.js
  10. 4
      src/views/QR/Content/components/PPT.js
  11. 42
      src/views/QR/Content/components/Tab.js
  12. 6
      src/views/QR/Content/components/Video.js
  13. 6
      src/views/QR/Content/components/Voice.js
  14. 58
      src/views/QR/Content/index.js
  15. 58
      src/views/QR/Scan/index.js
  16. 13
      src/views/QR/index.js

Binary file not shown.

@ -1,10 +1,9 @@
export default function MaterialAudioPlayer(props) {
import { file } from "../../redux/actions";
export default function MaterialAudioPlayer({ fileIds }) {
return (
<audio controls className="w-full h-10 mt-4">
<source
src="http://sv.bahar-music.ir/archive/S/Sadegh/Ho3ein%20Ft%20Sadegh%20-%20Shaba%20Radepa%20Tanhayi/Sadegh%20Ft%20Ho3ein%20-%20Shaba.mp3"
type="audio/mp3"
/>
<source src={`https://dnvn.ir/api/v1/file/${fileIds}`} type="audio/mp3" />
</audio>
);
}

@ -10,6 +10,7 @@ export { default as content } from "./content";
export { default as faq } from "./faq";
export { default as file } from "./file";
export {default as scrollAction} from "./scroll";
export {default as qr} from "./qr";

@ -0,0 +1,32 @@
import proxy from "../proxy";
const qr = {
list:
(data = {}) =>
async (dispatch) =>
await proxy.get("qr/list", data, { dispatch }),
info:
(data = {}) =>
async (dispatch) => {
await proxy.get("qr/info", data, { dispatch });
},
add:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.post("qr/add", data);
await proxy.get("qr/list", data2, { dispatch });
},
del:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.delete("ar/delete", data);
await proxy.get("ar/list", data2, { dispatch });
},
update:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.put("ar/update", data);
await proxy.get("ar/list", data2, { dispatch });
},
};
export default qr;

@ -9,6 +9,4 @@ export { default as file } from "./file";
export { default as userFactor } from "./userFactor";
export { default as userProduct } from "./userProduct";
export {default as scrollAction} from "./scroll";
export {default as qr} from "./qr";

@ -0,0 +1,32 @@
const initialState = {
loading: false,
error: null,
list: null,
};
export default function qr(state = initialState, action) {
let { type, data } = action;
switch (type) {
case "qr/list":
return { ...state, loading: false, error: null };
case "qr/update":
return { ...state, loading: false, error: null };
case "qr/add":
return { ...state, loading: false, error: null };
case "qr/delete":
return { ...state, loading: false, error: null };
case "qr/info":
return {
...state,
loading: false,
list: data,
error: null,
};
/////////////
case "loading":
return { ...state, loading: true };
case "error":
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -1,6 +1,6 @@
import React, { useEffect } from "react";
import { BrowserRouter, Routes, Route, } from "react-router-dom";
import { Navigate } from 'react-router-dom';
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Navigate } from "react-router-dom";
import { connect } from "react-redux";
import { publicApi } from "./redux/actions";
import Navbar from "./components/Navbar";
@ -35,7 +35,7 @@ function Router({
isLogin,
headerOptions,
setDesktopContentTransform,
footerOptions
footerOptions,
}) {
useEffect(() => {
window.addEventListener("scroll", () => {
@ -65,7 +65,7 @@ function Router({
>
<BrowserRouter>
{headerOptions?.shown && <Navbar headerOptions={headerOptions} />}
{isMobile && (
<>
<BG />
@ -160,25 +160,27 @@ function Router({
/>
}
/>
<Route
path='/videos'
<Route
path="/videos"
exact
element={
isMobile ?
<Videos
headerOptions={{
logo: true,
hamburgerMenu: true,
qr: true,
title: false,
back: false,
shown: true,
menu: false,
}}
/> : <Navigate replace to="/products" />
isMobile ? (
<Videos
headerOptions={{
logo: true,
hamburgerMenu: true,
qr: true,
title: false,
back: false,
shown: true,
menu: false,
}}
/>
) : (
<Navigate replace to="/products" />
)
}
>
</Route>
></Route>
<Route
path="/videos/:id"
exact
@ -227,6 +229,25 @@ function Router({
/>
}
/>
<Route
path="/scan/:id"
exact
element={
<QR
headerOptions={{
logo: false,
hamburgerMenu: false,
qr: false,
title: false,
back: true,
shown: true,
menu: true,
bookmark: false,
}}
page="content"
/>
}
/>
<Route
path="/orders"
exact
@ -347,9 +368,8 @@ function Router({
/>
}
/>
</Routes>
{headerOptions?.shown && <FooterDesign1 hasHeader/>}
{headerOptions?.shown && !isMobile && <FooterDesign1 hasHeader />}
</BrowserRouter>
</div>
</div>

@ -2,12 +2,12 @@ import React from "react";
import { Link } from "react-router-dom";
import linkIcon from "./links.svg";
export default function Links({ links }) {
export default function Links({ data }) {
return (
<div className="w-full flex-row justify-between items-center rounded-md bg-yellow-100 bg-opacity-20 py-3 px-2 mt-5 relative dark:bg-opacity-10">
<div className="flex flex-col">
<strong className="text-sm font-normal dark:text-white">لینک ها</strong>
{links.map((link, i) => (
{data.map((link, i) => (
<Link to="#" key={i} className="text-xs mt-1 dark:text-white">
{link}
</Link>

@ -1,10 +1,10 @@
import React from "react";
import pdfIcon from "./pdf.svg";
export default function PDF({ name, file }) {
export default function PDF({ data }) {
return (
<div className="w-full flex-row justify-between items-center rounded-md bg-red-100 bg-opacity-50 py-6 px-2 mt-5 relative dark:bg-opacity-10">
<strong className="text-right text-red-900 text-xs font-normal dark:text-white">{name}</strong>
<strong className="text-right text-red-900 text-xs font-normal dark:text-white">{data.name}</strong>
<img src={pdfIcon} className="w-8 absolute left-2 top-1/2 transform -translate-y-1/2" />
</div>
);

@ -2,11 +2,11 @@ import React from "react";
import pptIcon from "./ppt.png";
export default function PPT({ name, file }) {
export default function PPT({ data }) {
return (
<div className="w-full flex-row-reverse justify-between items-center rounded-md bg-green-100 bg-opacity-50 py-6 px-2 mt-5 relative dark:bg-opacity-10">
<strong className="text-right text-green-900 text-xs font-normal dark:text-white">
{name}
{data.name}
</strong>
<img
src={pptIcon}

@ -15,7 +15,7 @@ export default function Tab({ data }) {
<div className="w-full flex flex-row justify-between">
<button
onClick={() => setDataType("all")}
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-xs dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-sm dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
dataType === "all"
? "bg-blueFF1 font-medium"
: "bg-white font-normal"
@ -25,7 +25,7 @@ export default function Tab({ data }) {
</button>
<button
onClick={() => setDataType("voice")}
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-xs dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-sm dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
dataType === "voice"
? "bg-blueFF1 font-medium"
: "bg-white font-normal"
@ -35,7 +35,7 @@ export default function Tab({ data }) {
</button>
<button
onClick={() => setDataType("video")}
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-xs dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-sm dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
dataType === "video"
? "bg-blueFF1 font-medium"
: "bg-white font-normal"
@ -45,7 +45,7 @@ export default function Tab({ data }) {
</button>
<button
onClick={() => setDataType("pdf")}
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-xs dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-sm dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
dataType === "pdf"
? "bg-blueFF1 font-medium"
: "bg-white font-normal"
@ -55,7 +55,7 @@ export default function Tab({ data }) {
</button>
<button
onClick={() => setDataType("ppt")}
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-xs dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-sm dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
dataType === "ppt"
? "bg-blueFF1 font-medium"
: "bg-white font-normal"
@ -65,7 +65,7 @@ export default function Tab({ data }) {
</button>
<button
onClick={() => setDataType("links")}
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-xs dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
className={`py-2 w-1/6 border-b border-solid text-blueC0 text-sm dark:bg-opacity-10 dark:text-white border-blueFF1 dark:border-opacity-10 ${
dataType === "links"
? "bg-blueFF1 font-medium"
: "bg-white font-normal"
@ -78,58 +78,58 @@ export default function Tab({ data }) {
{dataType === "all" && (
<>
{data.voice && (
<Voice name={data.voice.name} file={data.voice.file} />
<Voice data={data?.voice} />
)}
{data.video && (
<Video name={data.video.name} file={data.voice.file} />
<Video data={data?.video} />
)}
{data.ppt && <PPT name={data.ppt.name} file={data.ppt.file} />}
{data.pdf && <PDF name={data.ppt.name} file={data.ppt.file} />}
{data.links && <Links links={data.links} />}
{data.ppt && <PPT data={data.ppt} />}
{data.pdf && <PDF data={data.pdf} />}
{data.links && <Links data={data.links} />}
</>
)}
{dataType === "voice" && (
<>
{data.voice ? (
<Voice name={data.voice.name} file={data.voice.file} />
<Voice data={data.voice} />
) : (
<p className="text-xs text-gray70">فایل صدا یافت نشد.</p>
<p className="text-sm text-gray70">فایل صدا یافت نشد.</p>
)}
</>
)}
{dataType === "video" && (
<>
{data.video ? (
<Video name={data.video.name} file={data.voice.file} />
<Video data={data.video} />
) : (
<p className="text-xs text-gray70">فایل تصویری یافت نشد.</p>
<p className="text-sm text-gray70">فایل تصویری یافت نشد.</p>
)}
</>
)}
{dataType === "ppt" && (
<>
{data.ppt ? (
<PPT name={data.ppt.name} file={data.ppt.file} />
<PPT data={data.ppt} />
) : (
<p className="text-xs text-gray70">فایل پاورپوینت یافت نشد.</p>
<p className="text-sm text-gray70">فایل پاورپوینت یافت نشد.</p>
)}
</>
)}
{dataType === "pdf" && (
<>
{data.pdf ? (
<PDF name={data.pdf.name} file={data.pdf.file} />
<PDF data={data.pdf} />
) : (
<p className="text-xs text-gray70">فایل پی دی اف یافت نشد.</p>
<p className="text-sm text-gray70">فایل پی دی اف یافت نشد.</p>
)}
</>
)}
{dataType === "links" && (
<>
{data.links ? (
<Links name={data.links.name} links={data.links} />
<Links data={data.links} />
) : (
<p className="text-xs text-gray70">لینکی پیدا نشد.</p>
<p className="text-sm text-gray70">لینکی پیدا نشد.</p>
)}
</>
)}

@ -1,17 +1,17 @@
import React from "react";
export default function Video({ name, file }) {
export default function Video({ data }) {
return (
<div className="w-full flex-col mt-5">
<strong className="w-full text-right text-green-900 mb-2 text-xs font-normal">
{name}
{data.name}
</strong>
<div className="w-full rounded-md overflow-hidden mt-4">
<video
style={{ width: "100%", height: "calc(100vw * 9 / 16 - 32)" }}
controls
>
<source src={`https://dnvn.ir/api/v1/file/20540`} type="video/mp4" />
<source src={`https://dnvn.ir/api/v1/file/${data.fileIds}`} type="video/mp4" />
</video>
</div>
</div>

@ -2,13 +2,13 @@ import React from "react";
import MusicPlayer from "../../../../components/Audio";
export default function Voice({ name, file }) {
export default function Voice({ data }) {
return (
<div className="w-full flex-col rounded-md bg-green-200 bg-opacity-30 py-3 px-2 mt-4 dark:bg-opacity-10">
<strong className="w-full text-right text-green-900 text-xs font-normal dark:text-white">
{name}
{data.name}
</strong>
<MusicPlayer />
<MusicPlayer fileIds={data.fileIds} />
</div>
);
}

@ -1,56 +1,68 @@
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { publicApi } from "../../../redux/actions";
import { publicApi, qr } from "../../../redux/actions";
import Tab from "./components/Tab";
export const Content = ({ headerOptions, setHeaderOptions, setPage, data }) => {
export const Content = ({
headerOptions,
setHeaderOptions,
data,
getQrData,
grades,
}) => {
useEffect(() => {
setHeaderOptions({
logo: true,
hamburgerMenu: true,
qr: true,
title: false,
back: false,
shown: true,
menu: false,
});
const path = window.location.pathname;
console.log(path.slice(path.lastIndexOf("/") + 1, path.length));
setHeaderOptions(headerOptions);
getQrData({ tail: path.slice(path.lastIndexOf("/") + 1, path.length) });
}, []);
useEffect(() => {
if (data) {
console.log(data?.book?.name);
}
}, [data]);
return (
<div className="flex-1 flex flex-col px-4 pb-20">
<div className="flex w-full flex-row">
<img
className="rounded-md"
src={"https://dnvn.ir/api/v1/file/2105"}
src={`https://dnvn.ir/api/v1/file/${data?.book?.fileIds}`}
style={{ width: 80, height: 120 }}
/>
<div className="flex flex-col mr-3 pt-2">
<strong className="text-sm text-blue5F dark:text-white">
{data.name}
<strong className="text-base text-blue5F dark:text-white">
{data?.book?.name}
</strong>
<span className="text-xs text-blueC0 mt-1 dark:text-greenBA">
{data.grade}
<span className="text-sm text-blueC0 mt-2 dark:text-greenBA">
{grades[data?.book?.gradeId]}
</span>
<p className="text-xs mt-1 text-blueC0 dark:text-greenBA">{`شما در حال مشاهده صفحه ${data.page} هستید.`}</p>
<p className="text-sm mt-2 text-blueC0 dark:text-greenBA">{`شما در حال مشاهده صفحه ${data?.qr?.pageNumber} هستید.`}</p>
</div>
</div>
<Tab
data={{
voice: data.voice,
video: data.video,
pdf: data.pdf,
ppt: data.ppt,
links: data.links,
voice: data?.qr?.content?.filter((obj) => obj.type === 'voice')[0],
video: data?.qr?.content?.filter((obj) => obj.type === 'video')[0],
pdf: data?.qr?.content?.filter((obj) => obj.type === 'pdf')[0],
ppt: data?.qr?.content?.filter((obj) => obj.type === 'ppt')[0],
links: data?.qr?.content?.filter((obj) => obj.type === 'links')[0],
}}
/>
</div>
);
};
const mapStateToProps = (state) => ({});
const mapStateToProps = (state) => ({
data: state.qr.list,
grades: state.publicApi.grades,
});
const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions,
getQrData: qr.info,
};
export default connect(mapStateToProps, mapDispatchToProps)(Content);

@ -7,12 +7,14 @@ import laptopImage from "../../../assets/images/laptop.svg";
const facingMode = ["environment", "user"];
export const Scan = ({ headerOptions, setHeaderOptions, setPage }) => {
const navigation = useNavigate();
const [result, setResult] = useState("");
export const Scan = ({
headerOptions,
setHeaderOptions,
}) => {
const navigate = useNavigate();
const handleScan = (data) => {
setResult(data);
navigate(`/scan/${data}`);
};
const handleError = (err) => {
@ -28,32 +30,30 @@ export const Scan = ({ headerOptions, setHeaderOptions, setPage }) => {
className="w-full h-screen bg-transparent px-0 transform -translate-y-16"
style={{ backgroundImage: `url(${laptopImage})` }}
>
{!result && (
<div className="w-full h-full flex flex-col justify-center bg-gray50 items-center px-6 bg-opacity-70 backdrop-filter backdrop-blur-sm">
<div className="rounded-3xl overflow-hidden w-full">
<Scanner
delay={300}
onError={handleError}
onScan={handleScan}
style={{ width: "100%" }}
facingMode={facingMode[1]}
/>
</div>
<strong className="mt-4 text-white text-xl">
اسکن کد QR فعالسازی کتاب
</strong>
<p className="text-sm text-white text-center mt-2 font-medium leading-5">
کد کیو آر روی کارت فعالسازی را با دوربین گوشی اسکن کنید تا محتوای
دیجیتال مربوط به کتاب برای شما فعال شود
</p>
<button
onClick={() => navigation(-1)}
className="py-3 mt-16 w-2/5 rounded-3xl border-2 border-solid border-blueB9 text-white text-lg font-semibold"
>
بازگشت
</button>
<div className="w-full h-full flex flex-col justify-center bg-gray50 items-center px-6 bg-opacity-70 backdrop-filter backdrop-blur-sm">
<div className="rounded-3xl overflow-hidden w-full">
<Scanner
delay={300}
onError={handleError}
onScan={handleScan}
style={{ width: "100%" }}
facingMode={facingMode[1]}
/>
</div>
)}
<strong className="mt-4 text-white text-xl">
اسکن کد QR فعالسازی کتاب
</strong>
<p className="text-sm text-white text-center mt-2 font-medium leading-5">
کد کیو آر روی کارت فعالسازی را با دوربین گوشی اسکن کنید تا محتوای
دیجیتال مربوط به کتاب برای شما فعال شود
</p>
<button
onClick={() => navigate(-1)}
className="py-3 mt-16 w-2/5 rounded-3xl border-2 border-solid border-blueB9 text-white text-lg font-semibold"
>
بازگشت
</button>
</div>
</div>
);
};

@ -1,9 +1,12 @@
import React, { useState } from "react";
import {connect} from 'react-redux';
import {qr} from '../../redux/actions';
import Scan from "./Scan";
import Content from "./Content";
function QR({ headerOptions, page }) {
const [currentPage, setCurrentPage] = useState(page);
return (
<>
{currentPage === "scan" && (
@ -16,4 +19,12 @@ function QR({ headerOptions, page }) {
);
}
export default QR;
const mapStateToProps = (state) => ({
});
const mapDispatchToProps = {
getData : qr.info
}
export default connect()(QR);

Loading…
Cancel
Save