Merge branch 'master' of https://git.sitenevis.com/Danovin/application Conflicts: yarn.lockmaster
commit
f443fe281c
120 changed files with 2204 additions and 1489 deletions
@ -0,0 +1,6 @@ |
|||||||
|
module.exports = { |
||||||
|
plugins: { |
||||||
|
tailwindcss: {}, |
||||||
|
autoprefixer: {}, |
||||||
|
}, |
||||||
|
} |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,24 @@ |
|||||||
|
import React from "react"; |
||||||
|
|
||||||
|
export default function Modal({ children, open, onClose }) { |
||||||
|
const [animationFlag, setAnimationFlag] = React.useState(false); |
||||||
|
|
||||||
|
React.useEffect(() => { |
||||||
|
setAnimationFlag(true); |
||||||
|
|
||||||
|
return () => { |
||||||
|
setAnimationFlag(false); |
||||||
|
}; |
||||||
|
}, []); |
||||||
|
|
||||||
|
return open ? ( |
||||||
|
<div |
||||||
|
className={`w-full h-full fixed top-0 left-0 z-50 flex items-center justify-center backdrop-filter backdrop-blur-sm bg-black bg-opacity-25 transform transition-all duration-500 origin-center ${ |
||||||
|
animationFlag ? "scale-100" : "scale-0" |
||||||
|
}`}
|
||||||
|
onClick={() => onClose()} |
||||||
|
> |
||||||
|
{children} |
||||||
|
</div> |
||||||
|
) : null; |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
|
||||||
|
const config = { |
||||||
|
setDevice: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "config/setDevice", data }), |
||||||
|
getAvailableForSell: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("config/availableForSell", data, { dispatch }), |
||||||
|
}; |
||||||
|
|
||||||
|
export default config; |
@ -0,0 +1,24 @@ |
|||||||
|
const initialState = { |
||||||
|
device: "mobile", |
||||||
|
availableForSell: [], |
||||||
|
}; |
||||||
|
|
||||||
|
export default function config(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "config/setDevice": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
device: data, |
||||||
|
}; |
||||||
|
case "config/availableForSell": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
availableForSell: data.productTypes, |
||||||
|
error: null, |
||||||
|
}; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
import React from "react"; |
||||||
|
import { connect } from "react-redux"; |
||||||
|
import { useNavigate } from "react-router-dom"; |
||||||
|
|
||||||
|
const height = { |
||||||
|
mobile: "calc((100vw - 32px) / 16 * 9)", |
||||||
|
tablet: "calc((100vw - 32px) / 16 * 9)", |
||||||
|
desktop: "calc((100vw / 12 * 11) / 4 / 16 * 9)", |
||||||
|
}; |
||||||
|
|
||||||
|
export const Blog = ({ blog, device }) => { |
||||||
|
const navigation = useNavigate(); |
||||||
|
return ( |
||||||
|
<article className="flex w-full lg:w-1/4 p-2"> |
||||||
|
<div |
||||||
|
className="cursor-pointer flex flex-col gap-4 w-full" |
||||||
|
onClick={() => |
||||||
|
navigation(`/blogs/${blog?.id}`, { state: { id: blog?.id } }) |
||||||
|
} |
||||||
|
> |
||||||
|
<div |
||||||
|
className="w-full rounded-md" |
||||||
|
style={{ |
||||||
|
backgroundImage: `url(https://dnvn.ir/api/v1/file/${blog?.fileIds})`, |
||||||
|
backgroundRepeat: "no-repeat", |
||||||
|
backgroundPosition: "center", |
||||||
|
backgroundSize: "cover", |
||||||
|
minHeight: height[device], |
||||||
|
}} |
||||||
|
></div> |
||||||
|
<strong className="text-sm lg:text-tiny xl:text-base text-backgroundText h-20"> |
||||||
|
{blog?.title} |
||||||
|
</strong> |
||||||
|
</div> |
||||||
|
</article> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({ |
||||||
|
device: state.config.device, |
||||||
|
}); |
||||||
|
|
||||||
|
const mapDispatchToProps = {}; |
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Blog); |
@ -1,73 +1,112 @@ |
|||||||
import React from "react"; |
import React from "react"; |
||||||
import separate from '../../../utils/separate'; |
import separate from "../../../utils/separate"; |
||||||
|
|
||||||
//components
|
//components
|
||||||
import StarRating from "../../../components/StarRating"; |
import StarRating from "../../../components/StarRating"; |
||||||
import Progress from "../../../components/Progress"; |
import Progress from "../../../components/Progress"; |
||||||
|
|
||||||
|
function Rate({ desktop, productId, rateDetail }) { |
||||||
|
const fiveCount = React.useMemo(() => { |
||||||
|
return rateDetail?.find((rate) => rate?.rate === 5); |
||||||
|
}, [rateDetail]); |
||||||
|
|
||||||
|
const fourCount = React.useMemo(() => { |
||||||
|
return rateDetail?.find((rate) => rate?.rate === 4); |
||||||
|
}, [rateDetail]); |
||||||
|
|
||||||
|
const threeCount = React.useMemo(() => { |
||||||
|
return rateDetail?.find((rate) => rate?.rate === 3); |
||||||
|
}, [rateDetail]); |
||||||
|
|
||||||
|
const twoCount = React.useMemo(() => { |
||||||
|
return rateDetail?.find((rate) => rate?.rate === 2); |
||||||
|
}, [rateDetail]); |
||||||
|
|
||||||
|
const oneCount = React.useMemo(() => { |
||||||
|
return rateDetail?.find((rate) => rate?.rate === 1); |
||||||
|
}, [rateDetail]); |
||||||
|
|
||||||
|
const allCount = React.useMemo(() => { |
||||||
|
return rateDetail?.reduce((a, b) => a + b?.count, 0); |
||||||
|
}, [rateDetail]); |
||||||
|
|
||||||
|
const rate = React.useMemo(() => { |
||||||
|
return rateDetail?.length |
||||||
|
? ((oneCount?.count || 0) * 1 + |
||||||
|
(twoCount?.count || 0) * 2 + |
||||||
|
(threeCount?.count || 0) * 3 + |
||||||
|
(fourCount?.count || 0) * 4 + |
||||||
|
(fiveCount?.count || 0) * 5) / |
||||||
|
rateDetail?.length |
||||||
|
: 0; |
||||||
|
}, [rateDetail]); |
||||||
|
|
||||||
function Rate({ avarage, all, fields, desktop }) { |
|
||||||
return ( |
return ( |
||||||
<div className="w-full flex flex-row justify-between items-center mt-5"> |
<div className="w-full flex justify-between items-center mt-5"> |
||||||
<div className="flex flex-col items-center justify-center h-full ml-4"> |
<div className="flex flex-col items-center justify-center h-full ml-4"> |
||||||
{ |
{desktop ? ( |
||||||
desktop ? |
|
||||||
<h1 className={`text-gray-600 mb-2 font-bold dark:text-white`}> |
<h1 className={`text-gray-600 mb-2 font-bold dark:text-white`}> |
||||||
{avarage} |
{rate} |
||||||
</h1> |
</h1> |
||||||
: |
) : ( |
||||||
<strong className={`text-blue5F mb-2 font-bold dark:text-white`} style={{ fontSize: 'calc(100vw / 10)' }}> |
<strong |
||||||
{avarage} |
className={`text-blue5F mb-2 font-bold dark:text-white`} |
||||||
|
style={{ fontSize: "calc(100vw / 10)" }} |
||||||
|
> |
||||||
|
{rate} |
||||||
</strong> |
</strong> |
||||||
} |
)} |
||||||
<div className=""> |
<div className=""> |
||||||
<StarRating /> |
<StarRating value={rate} /> |
||||||
</div> |
</div> |
||||||
<span className="text-base text-gray70 mt-2 dark:text-white">{separate(all)}</span> |
<span className="text-base text-gray70 mt-2 dark:text-white"> |
||||||
|
{" "} |
||||||
|
{`از بین ${allCount} نفر`} |
||||||
|
</span> |
||||||
</div> |
</div> |
||||||
<ul className="p-0 m-0 list-none flex flex-col flex-1"> |
<ul className="p-0 m-0 list-none flex flex-col flex-1"> |
||||||
{fields.map((item, index) => ( |
{[ |
||||||
<li key={index} className="w-full flex flex-row-reverse items-center justify-between"> |
|
||||||
<span className="mr-2 text-xs text-blue5F dark:text-white">{item.name}</span> |
|
||||||
|
|
||||||
{ |
|
||||||
desktop ? <Progress deskTop percent={item.percent} /> : <Progress percent={item.percent} /> |
|
||||||
} |
|
||||||
|
|
||||||
<span className="ml-2 text-xs text-blue5F dark:text-white">{item.percent + "%"}</span> |
|
||||||
</li> |
|
||||||
))} |
|
||||||
</ul> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
export default Rate; |
|
||||||
|
|
||||||
Rate.defaultProps = { |
|
||||||
avarage: 4.8, |
|
||||||
all: 4780, |
|
||||||
fields: [ |
|
||||||
{ |
{ |
||||||
name: "5 ستاره", |
name: "یک ستاره", |
||||||
percent: 49, |
value: ((oneCount?.count || 0) / allCount) * 100, |
||||||
}, |
}, |
||||||
{ |
{ |
||||||
name: "4 ستاره", |
name: "دو ستاره", |
||||||
percent: 31, |
value: ((twoCount?.count || 0) / allCount) * 100, |
||||||
}, |
}, |
||||||
{ |
{ |
||||||
name: "3 ستاره", |
name: "سه ستاره", |
||||||
percent: 9, |
value: ((threeCount?.count || 0) / allCount) * 100, |
||||||
}, |
}, |
||||||
{ |
{ |
||||||
name: "2 ستاره", |
name: "چهار ستاره", |
||||||
percent: 5, |
value: ((fourCount?.count || 0) / allCount) * 100, |
||||||
}, |
}, |
||||||
{ |
{ |
||||||
name: "1 ستاره", |
name: "پنج ستاره", |
||||||
percent: 6, |
value: ((fiveCount?.count || 0) / allCount) * 100, |
||||||
}, |
}, |
||||||
], |
].map((item, index) => ( |
||||||
}; |
<li |
||||||
|
key={index} |
||||||
|
className="w-full flex flex-row-reverse items-center justify-between" |
||||||
|
> |
||||||
|
<span className="mr-2 text-xs text-blue5F dark:text-white"> |
||||||
|
{item.name} |
||||||
|
</span> |
||||||
|
{desktop ? ( |
||||||
|
<Progress deskTop percent={item.value} /> |
||||||
|
) : ( |
||||||
|
<Progress percent={item.value} /> |
||||||
|
)} |
||||||
|
<span className="ml-2 text-xs text-blue5F dark:text-white"> |
||||||
|
{item.value + "%"} |
||||||
|
</span> |
||||||
|
</li> |
||||||
|
))} |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export default Rate; |
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue