parent
fb80e688ab
commit
7e551c5a50
21 changed files with 675 additions and 20 deletions
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 309 KiB |
@ -0,0 +1,13 @@ |
||||
import React from "react"; |
||||
import "./index.scss"; |
||||
|
||||
export default function Radio(props) { |
||||
return ( |
||||
<div className="radio flex items-center"> |
||||
<input id="radio-1" name={props.name} type="radio" /> |
||||
<label htmlFor="radio-1" className="radio-label text-xs"> |
||||
{/* {props.label} */} |
||||
</label> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,58 @@ |
||||
$color1: #f4f4f4; |
||||
$color2: #3197EE; |
||||
|
||||
.radio { |
||||
input[type="radio"] { |
||||
position: absolute; |
||||
opacity: 0; |
||||
+ .radio-label { |
||||
&:before { |
||||
content: ''; |
||||
background: $color1; |
||||
border-radius: 100%; |
||||
border: 1px solid darken($color1, 25%); |
||||
display: inline-block; |
||||
width: 1.4em; |
||||
height: 1.4em; |
||||
position: relative; |
||||
vertical-align: top; |
||||
margin-left: 0.5em; |
||||
cursor: pointer; |
||||
text-align: center; |
||||
transition: all 250ms ease; |
||||
} |
||||
} |
||||
&:checked { |
||||
+ .radio-label { |
||||
&:before { |
||||
background-color: $color2; |
||||
box-shadow: inset 0 0 0 4px $color1; |
||||
} |
||||
} |
||||
} |
||||
&:focus { |
||||
+ .radio-label { |
||||
&:before { |
||||
outline: none; |
||||
border-color: $color2; |
||||
} |
||||
} |
||||
} |
||||
&:disabled { |
||||
+ .radio-label { |
||||
&:before { |
||||
box-shadow: inset 0 0 0 4px $color1; |
||||
border-color: darken($color1, 25%); |
||||
background: darken($color1, 25%); |
||||
} |
||||
} |
||||
} |
||||
+ .radio-label { |
||||
&:empty { |
||||
&:before { |
||||
margin-right: 0; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
import React, { useState } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import Button from "../../../components/Button"; |
||||
import Radio from "../../../components/Radio"; |
||||
|
||||
function Address({ addresses, isDark }) { |
||||
const [activeAddress, setActiveAddress] = useState(addresses[0]); |
||||
const Location = ({ address }) => { |
||||
return ( |
||||
<button |
||||
className={`flex flex-row border-2 border-solid items-center w-full px-3 py-4 rounded-md mt-4 transition-all duration-500 dark:bg-opacity-5 ${ |
||||
activeAddress === address |
||||
? "bg-blueFD border-blueC0" |
||||
: "bg-grayF9 border-gray45" |
||||
}`}
|
||||
> |
||||
<Radio /> |
||||
<div className="flex flex-1 flex-col mr-3"> |
||||
<li className="text-right text-xs text-blue52 dark:text-white leading-4"> |
||||
آدرس: {address.address} |
||||
</li> |
||||
<li className="text-right text-xs text-blue52 dark:text-white mt-1.5"> |
||||
نام تحویل گیرنده: {address.receiver} |
||||
</li> |
||||
<li className="text-right text-xs text-blue52 dark:text-white mt-1.5"> |
||||
کد پستی: {address.postalCode} |
||||
</li> |
||||
<li className="text-right text-xs text-blue52 dark:text-white mt-1.5"> |
||||
شماره تماس: {address.cellphone} |
||||
</li> |
||||
</div> |
||||
</button> |
||||
); |
||||
}; |
||||
return ( |
||||
<section className="mt-2"> |
||||
<strong className="font-medium dark:text-white">انتخاب آدرس</strong> |
||||
<ul className="list-none p-0 m-0 flex flex-col"> |
||||
{addresses.map((address, index) => ( |
||||
<Location address={address} key={index} /> |
||||
))} |
||||
</ul> |
||||
<div className="w-full flex flex-row justify-between items-center mt-4"> |
||||
<Button |
||||
title="یک آدرس جدید اضافه کنید +" |
||||
backgroundColor="bg-grayF9 dark:bg-blueC0 dark:bg-opacity-30" |
||||
border={{ color: isDark ? '#DBDBDB22' : "#DBDBDB", width: "1px" }} |
||||
bgOpacity="bg-opacity-100" |
||||
width="100%" |
||||
color={isDark ? "text-white" : "text-gray70"} |
||||
/> |
||||
</div> |
||||
</section> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
isDark: state.publicApi.isDark, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Address); |
@ -0,0 +1,36 @@ |
||||
import React, { useState } from "react"; |
||||
import { connect } from "react-redux"; |
||||
|
||||
function PaymentMethods({ paymentMethods, isDark }) { |
||||
const [activeMethod, setActiveMactiveMethod] = useState(paymentMethods[0]); |
||||
const Method = ({ method }) => { |
||||
return ( |
||||
<button |
||||
className={`flex flex-col border border-solid items-center w-full px-2.5 py-3.5 rounded-md mt-4 relative transition-all duration-500 dark:text-white ${ |
||||
activeMethod === method |
||||
? "bg-blueFD border-blueC0 text-blueC0 bg-opacity-5" |
||||
: "bg-grayF9 border-grayDB text-gray70 bg-opacity-5" |
||||
}`}
|
||||
onClick={() => setActiveMactiveMethod(method)} |
||||
> |
||||
{method.name} |
||||
</button> |
||||
); |
||||
}; |
||||
return ( |
||||
<section className="mt-8"> |
||||
<strong className="font-medium dark:text-white">انتخاب شیوه پرداخت</strong> |
||||
<ul className="list-none p-0 m-0 flex flex-row justify-between flex-wrap"> |
||||
{paymentMethods.map((method, index) => ( |
||||
<Method method={method} key={index} /> |
||||
))} |
||||
</ul> |
||||
</section> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
isDark: state.publicApi.isDark, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(PaymentMethods); |
@ -0,0 +1,53 @@ |
||||
import React, { useState } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import Button from "../../../components/Button"; |
||||
import Radio from "../../../components/Radio"; |
||||
|
||||
function TransportDate({ transportDate, isDark }) { |
||||
const [activeDate, setActiveDate] = useState(transportDate?.times[0]); |
||||
const Time = ({ time }) => { |
||||
return ( |
||||
<button |
||||
className={`flex flex-col border border-solid items-center flex-1 mx-1 px-2 py-3 rounded-md mt-4 relative transition-all duration-500 ${ |
||||
activeDate === time |
||||
? "bg-blueFD border-blueC0 dark:bg-opacity-5" |
||||
: "bg-grayF9 border-grayDB dark:bg-opacity-5" |
||||
}`}
|
||||
onClick={() => setActiveDate(time)} |
||||
> |
||||
<strong |
||||
className={`text-sm transition-all duration-500 dark:text-white ${ |
||||
activeDate === time ? "text-blueC0" : "text-blue52" |
||||
}`}
|
||||
> |
||||
{time.time} |
||||
</strong> |
||||
{time.status === "completed" && ( |
||||
<span |
||||
className={`text-xs transition-all duration-500 dark:text-white ${ |
||||
activeDate === time ? "text-blueC0" : "text-blue52" |
||||
}`}
|
||||
> |
||||
تکمیل ظرفیت |
||||
</span> |
||||
)} |
||||
</button> |
||||
); |
||||
}; |
||||
return ( |
||||
<section className="mt-8"> |
||||
<strong className="font-medium dark:text-white">زمان ارسال را انتخاب کنید</strong> |
||||
<ul className="list-none p-0 m-0 flex flex-row justify-between flex-wrap"> |
||||
{transportDate.times.map((time, index) => ( |
||||
<Time time={time} key={index} /> |
||||
))} |
||||
</ul> |
||||
</section> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
isDark: state.publicApi.isDark, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(TransportDate); |
@ -0,0 +1,62 @@ |
||||
import React, { useState } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import Button from "../../../components/Button"; |
||||
import Radio from "../../../components/Radio"; |
||||
|
||||
function TransportMethod({ transportMethods, isDark }) { |
||||
const [activeMethod, setActiveMethod] = useState(transportMethods[0]); |
||||
const Method = ({ method }) => { |
||||
return ( |
||||
<button |
||||
className={`flex flex-col border border-solid items-center w-full px-2 py-3 rounded-md mt-4 relative transition-all duration-500 ${ |
||||
activeMethod === method |
||||
? "bg-blueFD border-blueC0 dark:bg-opacity-5" |
||||
: "bg-grayF9 border-grayDB dark:bg-opacity-5" |
||||
}`}
|
||||
onClick={() => setActiveMethod(method)} |
||||
> |
||||
<strong |
||||
className={`text-sm transition-all duration-500 ${ |
||||
activeMethod === method |
||||
? "text-blueC0 dark:text-white" |
||||
: "text-blue52 dark:text-white" |
||||
}`}
|
||||
> |
||||
{method.name} |
||||
</strong> |
||||
<span |
||||
className={`text-xs transition-all duration-500 ${ |
||||
activeMethod === method |
||||
? "text-blueC0 dark:text-white" |
||||
: "text-blue52 dark:text-white" |
||||
}`}
|
||||
> |
||||
هزینه ارسال {method.cost} |
||||
</span> |
||||
<img |
||||
src={method.icon} |
||||
alt={method.name} |
||||
className="w-7 absolute left-3 top-1/2 transform -translate-y-1/2" |
||||
/> |
||||
</button> |
||||
); |
||||
}; |
||||
return ( |
||||
<section className="mt-8"> |
||||
<strong className="font-medium dark:text-white"> |
||||
لطفا یک روش ارسال انتخاب کنید |
||||
</strong> |
||||
<ul className="list-none p-0 m-0 flex flex-col"> |
||||
{transportMethods.map((method, index) => ( |
||||
<Method method={method} key={index} /> |
||||
))} |
||||
</ul> |
||||
</section> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
isDark: state.publicApi.isDark, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(TransportMethod); |
@ -0,0 +1,18 @@ |
||||
import React, { useEffect } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import { publicApi } from "../../../redux/actions"; |
||||
|
||||
export const Content = ({ headerOptions, setHeaderOptions, setPage }) => { |
||||
useEffect(() => { |
||||
setHeaderOptions(headerOptions); |
||||
}); |
||||
return <div></div>; |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({}); |
||||
|
||||
const mapDispatchToProps = { |
||||
setHeaderOptions: publicApi.setHeaderOptions, |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Content); |
@ -0,0 +1,67 @@ |
||||
import React, { useState, useEffect } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import { publicApi } from "../../../redux/actions"; |
||||
import { useNavigate } from "react-router-dom"; |
||||
import Scanner from "react-qr-reader"; |
||||
import laptopImage from "../../../assets/images/laptop.svg"; |
||||
|
||||
const facingMode = ["environment", "user"]; |
||||
|
||||
export const Scan = ({ headerOptions, setHeaderOptions, setPage }) => { |
||||
const navigation = useNavigate(); |
||||
const [result, setResult] = useState(""); |
||||
|
||||
const handleScan = (data) => { |
||||
setResult(data); |
||||
}; |
||||
|
||||
const handleError = (err) => { |
||||
console.error(err); |
||||
}; |
||||
|
||||
useEffect(() => { |
||||
setHeaderOptions(headerOptions); |
||||
}); |
||||
|
||||
return ( |
||||
<div |
||||
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"> |
||||
کد کیو آر روی کارت فعالسازی را با دوربین گوشی اسکن کنید تا محتوای |
||||
دیجیتال مربوط به کتاب برای شما فعال شود |
||||
</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> |
||||
)} |
||||
</div> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({}); |
||||
|
||||
const mapDispatchToProps = { |
||||
setHeaderOptions: publicApi.setHeaderOptions, |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Scan); |
@ -0,0 +1,19 @@ |
||||
import React, { useState } from "react"; |
||||
import Scan from "./Scan"; |
||||
import Content from "./Content"; |
||||
|
||||
function QR({ headerOptions, page }) { |
||||
const [currentPage, setCurrentPage] = useState(page); |
||||
return ( |
||||
<> |
||||
{page === "scan" && ( |
||||
<Scan headerOptions={headerOptions} setPage={setCurrentPage} /> |
||||
)} |
||||
{page === "content" && ( |
||||
<Content headerOptions={headerOptions} setPage={setCurrentPage} /> |
||||
)} |
||||
</> |
||||
); |
||||
} |
||||
|
||||
export default QR; |
@ -0,0 +1,21 @@ |
||||
import React, { useState, useEffect, useCallback } from "react"; |
||||
import { Link } from "react-router-dom"; |
||||
import { connect } from "react-redux"; |
||||
import { book, publicApi } from "../../redux/actions"; |
||||
|
||||
|
||||
const Videos = ({ }) => { |
||||
return ( |
||||
<></> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
|
||||
}); |
||||
|
||||
const mapDispatchToProps = { |
||||
|
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Videos); |
Loading…
Reference in new issue