add calculation module and fix many bugs

This commit is contained in:
Amir Mohamadi
2021-01-27 18:51:06 +03:30
parent 9433eb84ac
commit 08a17401aa
70 changed files with 7133 additions and 5528 deletions
+101 -101
View File
@@ -5,125 +5,125 @@ const {body, validationResult} = require('express-validator')
const v_m = require('../validation_messages')
module.exports.create = [
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => {
if (category) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.en.name': value}).then(category => {
if (category) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => {
if (category) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
}),
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.en.name': value}).then(category => {
if (category) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const blogCategory = new BlogCategory({
blogCategory_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
},
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
})
blogCategory.save(err => {
if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save})
})
}
const blogCategory = new BlogCategory({
blogCategory_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
},
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
})
blogCategory.save(err => {
if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save})
})
}
]
module.exports.getAll = [
(req, res) => {
BlogCategory.find({}, (err, categories) => {
if (err) return res.status(500).json({message: err})
return res.json(categories)
})
}
(req, res) => {
BlogCategory.find({}, (err, categories) => {
if (err) return res.status(500).json({message: err})
return res.json(categories)
})
}
]
module.exports.getOne = [
(req, res) => {
BlogCategory.findById(req.params.id, (err, category) => {
if (err) return res.status(404).json({message: err})
return res.json(category)
})
}
(req, res) => {
BlogCategory.findById(req.params.id, (err, category) => {
if (err) return res.status(404).json({message: err})
return res.json(category)
})
}
]
module.exports.update = [
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => {
if (category && category._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.en.name': value}).then(category => {
if (category && category._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => {
if (category && category._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
}),
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.en.name': value}).then(category => {
if (category && category._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = {
blogCategory_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
},
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
BlogCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save})
})
}
const data = {
blogCategory_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
},
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
BlogCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save})
})
}
]
module.exports.delete = [
(req, res) => {
BlogPost.find({category: req.params.id}, (err, posts) => {
if (err) console.log(err)
if (!posts.length) {
BlogCategory.findByIdAndDelete(req.params.id, (err) => {
if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_save})
})
} else {
return res.status(500).json({message: 'نمیتوان دسته بندی هایی که دارای پست هستند را پاک کرد.'})
}
})
}
(req, res) => {
BlogPost.find({category: req.params.id}, (err, posts) => {
if (err) console.log(err)
if (!posts.length) {
BlogCategory.findByIdAndDelete(req.params.id, (err) => {
if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_save})
})
} else {
return res.status(500).json({message: 'نمیتوان دسته بندی هایی که دارای پست هستند را پاک کرد.'})
}
})
}
]
+212 -212
View File
@@ -5,246 +5,246 @@ const fs = require('fs')
const jimp = require('jimp')
const v_m = require('../validation_messages')
// local variables
const shortDescriptionLength = 500
const coverWidth = 1920
const coverHeight = 720
const coverQuality = 70
const thumbWith = 460
const thumbHeight = 320
module.exports.create = [
[
// title
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.fa.title': value}).then(post => {
if (post) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.en.title': value}).then(post => {
if (post) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
// description
body('fa_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('en_description')
.notEmpty().withMessage(v_m['fa'].required.description),
// short description
body('fa_short_description')
.notEmpty().withMessage(v_m['fa'].required.description)
.bail()
.isLength({max: 200}).withMessage(v_m['fa'].max_char.max200),
body('en_short_description')
.notEmpty().withMessage(v_m['fa'].required.description)
.bail()
.isLength({max: 200}).withMessage(v_m['fa'].max_char.max200),
body('category')
.notEmpty().withMessage(v_m['fa'].required.category)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
let cover
let coverName
// 460 X 320
// 1920 x 720
if (req.files && req.files.cover) {
cover = req.files.cover
coverName = 'blog_' + Date.now() + '.' + cover.mimetype.split('/')[1]
} else {
return res.status(422).json({validation: {cover: {msg: v_m['fa'].required.cover}}})
}
jimp.read(cover.data)
.then(img => {
img
.cover(1920, 720)
.quality(70)
.write(`./static/uploads/images/blog/${coverName}`)
.resize(460, jimp.AUTO)
.cover(460, 320)
.write(`./static/uploads/images/blog/thumb_${coverName}`)
[
// title
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.fa.title': value}).then(post => {
if (post) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.en.title': value}).then(post => {
if (post) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
const data = {
post_details: {
fa: {
title: req.body.fa_title,
description: req.body.fa_description,
short_description: req.body.fa_short_description
},
en: {
title: req.body.en_title,
description: req.body.en_description,
short_description: req.body.en_short_description
}
},
cover: coverName,
published: req.body.published,
category: req.body.category,
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
// description
body('fa_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('en_description')
.notEmpty().withMessage(v_m['fa'].required.description),
const post = new BlogPost(data)
post.save(err => {
if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save})
})
}
// short description
body('fa_short_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('en_short_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('category')
.notEmpty().withMessage(v_m['fa'].required.category)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
let cover
let coverName
if (req.files && req.files.cover) {
cover = req.files.cover
coverName = 'blog_' + Date.now() + '.' + cover.mimetype.split('/')[1]
} else {
return res.status(422).json({validation: {cover: {msg: v_m['fa'].required.cover}}})
}
jimp.read(cover.data)
.then(img => {
img
.cover(coverWidth, coverHeight)
.quality(coverQuality)
.write(`./static/uploads/images/blog/${coverName}`)
.resize(thumbWith, jimp.AUTO)
.cover(thumbWith, thumbHeight)
.write(`./static/uploads/images/blog/thumb_${coverName}`)
})
const data = {
post_details: {
fa: {
title: req.body.fa_title,
description: req.body.fa_description,
short_description: req.body.fa_short_description.slice(0, shortDescriptionLength) + ' ... '
},
en: {
title: req.body.en_title,
description: req.body.en_description,
short_description: req.body.en_short_description.slice(0, shortDescriptionLength) + ' ... '
}
},
cover: coverName,
published: req.body.published,
category: req.body.category,
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
const post = new BlogPost(data)
post.save(err => {
if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save})
})
}
]
module.exports.getAll = [
(req, res) => {
BlogPost.find({}).sort({_id: -1}).exec((err, posts) => {
if (err) console.log(err)
return res.json(posts)
})
}
(req, res) => {
BlogPost.find({}).sort({_id: -1}).exec((err, posts) => {
if (err) console.log(err)
return res.json(posts)
})
}
]
module.exports.getOne = [
(req, res) => {
BlogPost.findById(req.params.id, (err, post) => {
if (err) console.log(err)
return res.json(post)
})
}
(req, res) => {
BlogPost.findById(req.params.id, (err, post) => {
if (err) console.log(err)
return res.json(post)
})
}
]
module.exports.update = [
[
// title
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.fa.title': value}).then(post => {
if (post && post._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.en.title': value}).then(post => {
if (post && post._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
[
// title
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.fa.title': value}).then(post => {
if (post && post._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title)
.bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail()
.custom((value, {req}) => {
return BlogPost.findOne({'post_details.en.title': value}).then(post => {
if (post && post._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true
})
}),
// description
body('fa_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('en_description')
.notEmpty().withMessage(v_m['fa'].required.description),
// description
body('fa_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('en_description')
.notEmpty().withMessage(v_m['fa'].required.description),
// short description
body('fa_short_description')
.notEmpty().withMessage(v_m['fa'].required.description)
.bail()
.isLength({max: 200}).withMessage(v_m['fa'].max_char.max200),
body('en_short_description')
.notEmpty().withMessage(v_m['fa'].required.description)
.bail()
.isLength({max: 200}).withMessage(v_m['fa'].max_char.max200),
// short description
body('fa_short_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('en_short_description')
.notEmpty().withMessage(v_m['fa'].required.description),
body('category')
.notEmpty().withMessage(v_m['fa'].required.category)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
body('category')
.notEmpty().withMessage(v_m['fa'].required.category)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = {
post_details: {
fa: {
title: req.body.fa_title,
description: req.body.fa_description,
short_description: req.body.fa_short_description
},
en: {
title: req.body.en_title,
description: req.body.en_description,
short_description: req.body.en_short_description
}
},
published: req.body.published,
category: req.body.category,
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
const data = {
post_details: {
fa: {
title: req.body.fa_title,
description: req.body.fa_description,
short_description: req.body.fa_short_description.slice(0, shortDescriptionLength) + ' ... '
},
en: {
title: req.body.en_title,
description: req.body.en_description,
short_description: req.body.en_short_description.slice(0, shortDescriptionLength) + ' ... '
}
},
published: req.body.published,
category: req.body.category,
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
let cover
let coverName
if (req.files && req.files.cover) {
cover = req.files.cover
coverName = 'blog_' + Date.now() + '.' + cover.mimetype.split('/')[1]
data.cover = coverName
jimp.read(cover.data)
.then(img => {
img
.cover(coverWidth, coverHeight)
.quality(coverQuality)
.write(`./static/uploads/images/blog/${coverName}`)
.resize(thumbWith, jimp.AUTO)
.cover(thumbWith, thumbHeight)
.write(`./static/uploads/images/blog/thumb_${coverName}`)
})
}
BlogPost.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
if (cover && cover.data) {
fs.unlink(`./static/${oldData.cover}`, err => {
if (err) console.log(err)
})
fs.unlink(`./static/${oldData.thumb}`, err => {
if (err) console.log(err)
})
}
// 460 X 320
// 1920 x 720
let cover
let coverName
if (req.files && req.files.cover) {
cover = req.files.cover
coverName = 'blog_' + Date.now() + '.' + cover.mimetype.split('/')[1]
data.cover = coverName
jimp.read(cover.data)
.then(img => {
img
.cover(1920, 720)
.write(`./static/uploads/images/blog/${coverName}`)
.resize(460, jimp.AUTO)
.cover(460, 320)
.write(`./static/uploads/images/blog/thumb_${coverName}`)
})
}
BlogPost.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
if (cover && cover.data) {
fs.unlink(`./static/${oldData.cover}`, err => {
if (err) console.log(err)
})
fs.unlink(`./static/${oldData.thumb}`, err => {
if (err) console.log(err)
})
}
return res.json({message: v_m['fa'].response.success_save})
BlogPost.findById(oldData._id, (err, newData) => {
if (err) console.log(err)
return res.json(newData)
})
}
})
}
]
module.exports.delete = [
(req, res) => {
BlogPost.findByIdAndDelete(req.params.id, (err, post) => {
if (err) return res.status(404).json({message: err})
fs.unlink(`./static/${post.cover}`, err => {
if (err) console.log(err)
})
fs.unlink(`./static/${post.thumb}`, err => {
if (err) console.log(err)
})
return res.json({message: v_m['fa'].response.success_remove})
(req, res) => {
BlogPost.findByIdAndDelete(req.params.id, (err, post) => {
if (err) return res.status(404).json({message: err})
fs.unlink(`./static/${post.cover}`, err => {
if (err) console.log(err)
})
}
fs.unlink(`./static/${post.thumb}`, err => {
if (err) console.log(err)
})
return res.json({message: v_m['fa'].response.success_remove})
})
}
]
+665 -27
View File
@@ -2,34 +2,672 @@ const {body, validationResult} = require('express-validator')
const v_m = require('../validation_messages')
const validationMessages = {
fa: {},
en: {}
fa: {
method: 'روش محاسبه را انتخاب کنید',
method_not_supported: 'روش انتخاب شده پشتیبانی نشده است',
gratingType: 'نوع گریتینک را انتخاب کنید',
gratingType_not_supported: 'نوع گریتینگ پشتیبانی نشده است',
loadType: 'نوع فشار را وارد کنید',
class: 'کلاس را انتخاب کنید',
pointedLoad: 'مقدار بار متمرکز را وارد کنید',
distributedLoad: 'مقدار بار گسترده را وارد کنید',
bearingBarThickness: 'ضخامت تسمه باربر را وارد کنید',
bearingBarPitch: 'گام تسمه باربر را انتخاب کنید',
bearingBarPitch_not_ok: 'مقدار گام تسمه باربر صحیح نیست',
crossBarPitch: 'گام تسمه رابط را تنخاب کنید',
crossBarPitch_not_ok: 'مقدار گام تسمه رابط صحیح نیست',
bearingBarHeight: 'ارتفاع تسمه باربر را انتخاب کنید',
bearingBarHeight_not_ok: 'مقدار ارتفاع تسمه باربر صحیح نیست',
clearSpan: 'مقدار دهنه را وارد کنید',
sigma_ok: 'تنش مجاز',
sigma_out_of_range: 'تنش خارج از حد مجاز',
deflection_ok: 'خیز مجاز',
deflection_out_of_range: 'خیز خارج از حد مجاز'
},
en: {
method: 'Choose calculation method',
method_not_supported: 'Chosen calculation method not supported',
gratingType: 'Select the type of grating',
gratingType_not_supported: 'Grating type not supported',
loadType: 'Enter load type',
class: 'Select class',
pointedLoad: 'Enter the amount of pointed load',
distributedLoad: 'Enter the amount of distributed load',
bearingBarThickness: 'Enter bearing bar thickness',
bearingBarPitch: 'Select bearing bar pitch',
bearingBarPitch_not_ok: 'Bearing bar pitch value is incorrect',
crossBarPitch: 'Select cross bar pitch',
crossBarPitch_not_ok: 'Cross bar pitch value is incorrect',
bearingBarHeight: 'Select bearing bar height',
bearingBarHeight_not_ok: 'Bearing bar height is incorrect',
clearSpan: 'Enter clear span',
sigma_ok: 'Tension OK',
sigma_out_of_range: 'Tension Out Of Range',
deflection_ok: 'Deflection OK',
deflection_out_of_range: 'Deflection Out Of Range'
}
}
module.exports = [
[
body('method')
.notEmpty().withMessage(),
body('type')
.notEmpty().withMessage(),
body('class')
.notEmpty().withMessage(),
body('pointLoad')
.notEmpty().withMessage(),
body('distributedLoad')
.notEmpty().withMessage(),
body('bearingBarPitch')
.notEmpty().withMessage(),
body('crossBarPitCh')
.notEmpty().withMessage(),
body('clearSpan')
.notEmpty().withMessage(),
body('bearingBarThickness')
.notEmpty().withMessage(),
body('bearingBarHeight')
.notEmpty().withMessage()
],
(req, res) => {
const values = {
// ArakRail products
bearingBarPitch_forge: [30, 35, 41, 50],
bearingBarPitch_pressured: [11, 22, 33, 44, 50, 55],
// defined in formula
crossBarPitch_forge: [38, 50, 76, 100],
crossBarPitch_pressured: [11, 22, 33, 44, 50, 55, 66, 77, 88, 100],
// defined in formula
bearingBarHeight: [20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
}
}
function relativeBearingBarHeight(gratingType, crossBarPitch) {
// defined in formula
bearingBarHeight = values.bearingBarHeight
const CBPitch = Number(crossBarPitch)
if (gratingType === 'forge') {
if (CBPitch === 38) return bearingBarHeight.filter(item => item <= 80)
else return bearingBarHeight.filter(item => item <= 60)
} else if (gratingType === 'pressured') {
if (
CBPitch === 11 ||
CBPitch === 22 ||
CBPitch === 55 ||
CBPitch === 77 ||
CBPitch === 88
) return bearingBarHeight.filter(item => item <= 60)
else if (
CBPitch === 33 ||
CBPitch === 44 ||
CBPitch === 50 ||
CBPitch === 66 ||
CBPitch === 100
) return bearingBarHeight
}
}
module.exports.calculate = [
[
body('method')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].method
})
.bail()
.custom((value, {req}) => {
if (value === 'custom' || value === 'classified') return true
else return Promise.reject(validationMessages[req.body.locale].method_not_supported)
}),
body('gratingType')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].gratingType
})
.bail()
.custom((value, {req}) => {
if (value === 'forge' || value === 'pressured') return true
else return Promise.reject(validationMessages[req.body.locale].gratingType_not_supported)
}),
body('loadType')
.custom((value, {req}) => {
if (req.body.method === 'custom') {
if (value === 'pointedLoad' || value === 'distributedLoad') return true
else return Promise.reject(validationMessages[req.body.locale].loadType)
} else return true
}),
body('vehicleClass')
.custom((value, {req}) => {
if (req.body.method === 'classified') {
const classes = ['class1', 'class2', 'class3', 'class4', 'FL1', 'FL2', 'FL3', 'FL4', 'FL5', 'FL6']
if (classes.includes(value)) return true
else return Promise.reject(validationMessages[req.body.locale].class)
} else return true
}),
body('pointedLoadValue')
.custom((value, {req}) => {
if (req.body.method === 'custom') {
if (req.body.loadType === 'pointedLoad' && !value) return Promise.reject(validationMessages[req.body.locale].pointedLoad)
else return true
} else return true
})
.bail()
.if((value, {req}) => req.body.method === 'custom' && req.body.loadType === 'pointedLoad')
.isNumeric().withMessage((value, {req}) => {
return v_m[req.body.locale].format.number
}),
body('distributedLoadValue')
.custom((value, {req}) => {
if (req.body.method === 'custom') {
if (req.body.loadType === 'distributedLoad' && !value) return Promise.reject(validationMessages[req.body.locale].distributedLoad)
else return true
} else return true
})
.bail()
.if((value, {req}) => req.body.method === 'custom' && req.body.loadType === 'distributedLoad')
.isNumeric().withMessage((value, {req}) => {
return v_m[req.body.locale].format.number
}),
body('bearingBarThickness')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].bearingBarThickness
})
.bail()
.isNumeric().withMessage((value, {req}) => {
return v_m[req.body.locale].format.number
}),
body('bearingBarPitch')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].bearingBarPitch
})
.bail()
.isNumeric().withMessage((value, {req}) => {
return v_m[req.body.locale].format.number
})
.bail()
.custom((value, {req}) => {
if (req.body.gratingType === 'forge') {
if (values.bearingBarPitch_forge.includes(Number(value))) return true
else return Promise.reject(validationMessages[req.body.locale].bearingBarPitch_not_ok)
} else {
if (values.bearingBarPitch_pressured.includes(Number(value))) return true
else return Promise.reject(validationMessages[req.body.locale].bearingBarPitch_not_ok)
}
}),
body('crossBarPitch')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].crossBarPitch
})
.bail()
.isNumeric().withMessage((value, {req}) => {
return v_m[req.body.locale].format.number
})
.bail()
.custom((value, {req}) => {
if (req.body.gratingType === 'forge') {
if (values.crossBarPitch_forge.includes(Number(value))) return true
else return Promise.reject(validationMessages[req.body.locale].crossBarPitch_not_ok)
} else {
if (values.crossBarPitch_pressured.includes(Number(value))) return true
else return Promise.reject(validationMessages[req.body.locale].crossBarPitch_not_ok)
}
}),
body('bearingBarHeight')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].bearingBarHeight
})
.bail()
.isNumeric().withMessage((value, {req}) => {
return v_m[req.body.locale].format.number
})
.bail()
.custom((value, {req}) => {
if (relativeBearingBarHeight(req.body.gratingType, req.body.crossBarPitch).includes(Number(value))) return true
else return Promise.reject(validationMessages[req.body.locale].bearingBarHeight_not_ok)
}),
body('clearSpan')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].clearSpan
})
.bail()
.isNumeric().withMessage((value, {req}) => {
return v_m[req.body.locale].format.number
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
let method = req.body.method
let gratingType = req.body.gratingType
let loadType = req.body.loadType
let vehicleClass = req.body.vehicleClass
let bearingBarHeight = req.body.bearingBarHeight
let bearingBarThickness = req.body.bearingBarThickness
let bearingBarPitch = req.body.bearingBarPitch
let crossBarPitch = req.body.crossBarPitch
let clearSpan = req.body.clearSpan
let locale = req.body.locale
///////// classified vehicles
const vehiclesClasses = {
'class1': {
distributedLoad: 6
},
'class2': {
pointedLoad: 10,
c4: 200,
d4: 200
},
'class3': {
pointedLoad: 30,
c4: 200,
d4: 400
},
'class4': {
pointedLoad: 90,
c4: 250,
d4: 600
},
'FL1': {
pointedLoad: 26,
c4: 130,
d4: 130
},
'FL2': {
pointedLoad: 40,
c4: 150,
d4: 175
},
'FL3': {
pointedLoad: 63,
c4: 200,
d4: 200
},
'FL4': {
pointedLoad: 90,
c4: 200,
d4: 300
},
'FL5': {
pointedLoad: 140,
c4: 200,
d4: 375
},
'FL6': {
pointedLoad: 170,
c4: 200,
d4: 450
},
}
///////// pointed load
function pointedLoad() {
// static variables
const forge = gratingType === 'forge'
const custom = method === 'custom'
// computing m | c4 | d4 | pointedLoadValue
function m_pressured(bearingBarHeight, crossBarPitch) {
const CBPitch = Number(crossBarPitch)
const BBHeight = Number(bearingBarHeight)
if (BBHeight === 20) {
if (CBPitch === 11) return 4.00
if (CBPitch === 22) return 4.00
if (CBPitch === 33) return 3.33
if (CBPitch === 44) return 2.50
if (CBPitch === 50) return 2.22
if (CBPitch === 55) return 2.00
if (CBPitch === 66) return 1.68
if (CBPitch === 77) return 1.43
if (CBPitch === 88) return 1.25
if (CBPitch === 100) return 1.11
} else if (BBHeight === 25) {
if (CBPitch === 11) return 3.85
if (CBPitch === 22) return 3.85
if (CBPitch === 33) return 3.25
if (CBPitch === 44) return 2.45
if (CBPitch === 50) return 2.17
if (CBPitch === 55) return 1.95
if (CBPitch === 66) return 1.62
if (CBPitch === 77) return 1.40
if (CBPitch === 88) return 1.21
if (CBPitch === 100) return 1.08
} else if (BBHeight === 30) {
if (CBPitch === 11) return 3.80
if (CBPitch === 22) return 3.77
if (CBPitch === 33) return 3.17
if (CBPitch === 44) return 2.40
if (CBPitch === 50) return 2.15
if (CBPitch === 55) return 1.90
if (CBPitch === 66) return 1.58
if (CBPitch === 77) return 1.35
if (CBPitch === 88) return 1.19
if (CBPitch === 100) return 1.06
} else if (BBHeight === 35) {
if (CBPitch === 11) return 3.75
if (CBPitch === 22) return 3.75
if (CBPitch === 33) return 3.08
if (CBPitch === 44) return 2.32
if (CBPitch === 50) return 2.05
if (CBPitch === 55) return 1.86
if (CBPitch === 66) return 1.54
if (CBPitch === 77) return 1.33
if (CBPitch === 88) return 1.17
if (CBPitch === 100) return 1.02
} else if (BBHeight === 40) {
if (CBPitch === 11) return 3.70
if (CBPitch === 22) return 3.65
if (CBPitch === 33) return 3.00
if (CBPitch === 44) return 2.25
if (CBPitch === 50) return 2.00
if (CBPitch === 55) return 1.80
if (CBPitch === 66) return 1.52
if (CBPitch === 77) return 1.28
if (CBPitch === 88) return 1.12
if (CBPitch === 100) return 1.01
} else if (BBHeight === 45) {
if (CBPitch === 11) return 3.65
if (CBPitch === 22) return 3.50
if (CBPitch === 33) return 2.92
if (CBPitch === 44) return 2.18
if (CBPitch === 50) return 1.95
if (CBPitch === 55) return 1.75
if (CBPitch === 66) return 1.46
if (CBPitch === 77) return 1.25
if (CBPitch === 88) return 1.09
if (CBPitch === 100) return 0.97
} else if (BBHeight === 50) {
if (CBPitch === 11) return 3.45
if (CBPitch === 22) return 3.41
if (CBPitch === 33) return 2.83
if (CBPitch === 44) return 2.10
if (CBPitch === 50) return 1.88
if (CBPitch === 55) return 1.69
if (CBPitch === 66) return 1.42
if (CBPitch === 77) return 1.22
if (CBPitch === 88) return 1.06
if (CBPitch === 100) return 0.94
} else if (BBHeight === 55) {
if (CBPitch === 11) return 3.28
if (CBPitch === 22) return 3.26
if (CBPitch === 33) return 2.75
if (CBPitch === 44) return 2.08
if (CBPitch === 50) return 1.84
if (CBPitch === 55) return 1.66
if (CBPitch === 66) return 1.39
if (CBPitch === 77) return 1.18
if (CBPitch === 88) return 1.04
if (CBPitch === 100) return 0.92
} else if (BBHeight === 60) {
if (CBPitch === 11) return 3.20
if (CBPitch === 22) return 3.18
if (CBPitch === 33) return 2.67
if (CBPitch === 44) return 1.98
if (CBPitch === 50) return 1.76
if (CBPitch === 55) return 1.59
if (CBPitch === 66) return 1.35
if (CBPitch === 77) return 1.14
if (CBPitch === 88) return 0.99
if (CBPitch === 100) return 0.89
} else if (BBHeight === 65) {
if (CBPitch === 33) return 2.58
if (CBPitch === 44) return 1.93
if (CBPitch === 50) return 1.71
if (CBPitch === 66) return 1.30
if (CBPitch === 100) return 0.86
} else if (BBHeight === 70) {
if (CBPitch === 33) return 2.50
if (CBPitch === 44) return 1.88
if (CBPitch === 50) return 1.66
if (CBPitch === 66) return 1.25
if (CBPitch === 100) return 0.83
} else if (BBHeight === 75) {
if (CBPitch === 33) return 2.42
if (CBPitch === 44) return 1.82
if (CBPitch === 50) return 1.62
if (CBPitch === 66) return 1.20
if (CBPitch === 100) return 0.81
} else if (BBHeight === 80) {
if (CBPitch === 33) return 2.33
if (CBPitch === 44) return 1.75
if (CBPitch === 50) return 1.58
if (CBPitch === 66) return 1.15
if (CBPitch === 100) return 0.78
} else if (BBHeight === 85) {
if (CBPitch === 33) return 2.25
if (CBPitch === 44) return 1.71
if (CBPitch === 50) return 1.52
if (CBPitch === 66) return 1.13
if (CBPitch === 100) return 0.75
} else if (BBHeight === 90) {
if (CBPitch === 33) return 2.17
if (CBPitch === 44) return 1.67
if (CBPitch === 50) return 1.45
if (CBPitch === 66) return 1.11
if (CBPitch === 100) return 0.72
} else if (BBHeight === 95) {
if (CBPitch === 33) return 2.08
if (CBPitch === 44) return 1.59
if (CBPitch === 50) return 1.39
if (CBPitch === 66) return 1.05
if (CBPitch === 100) return 0.69
} else if (BBHeight === 100) {
if (CBPitch === 33) return 2.00
if (CBPitch === 44) return 1.50
if (CBPitch === 50) return 1.33
if (CBPitch === 66) return 0.99
if (CBPitch === 100) return 0.66
}
}
function m_forge(bearingBarHeight, crossBarPitch) {
const CBPitch = Number(crossBarPitch)
const BBHeight = Number(bearingBarHeight)
if (BBHeight === 20) {
if (CBPitch === 38) return 2.25
if (CBPitch === 50) return 1.35
if (CBPitch === 76) return 0.81
if (CBPitch === 100) return 0.52
} else if (BBHeight === 25) {
if (CBPitch === 38) return 2.19
if (CBPitch === 50) return 1.28
if (CBPitch === 76) return 0.77
if (CBPitch === 100) return 0.52
} else if (BBHeight === 30) {
if (CBPitch === 38) return 2.13
if (CBPitch === 50) return 1.25
if (CBPitch === 76) return 0.75
if (CBPitch === 100) return 0.48
} else if (BBHeight === 35) {
if (CBPitch === 38) return 2.06
if (CBPitch === 50) return 1.20
if (CBPitch === 76) return 0.71
if (CBPitch === 100) return 0.47
} else if (BBHeight === 40) {
if (CBPitch === 38) return 2.00
if (CBPitch === 50) return 1.17
if (CBPitch === 76) return 0.67
if (CBPitch === 100) return 0.45
} else if (BBHeight === 45) {
if (CBPitch === 38) return 1.94
if (CBPitch === 50) return 1.11
if (CBPitch === 76) return 0.65
if (CBPitch === 100) return 0.43
} else if (BBHeight === 50) {
if (CBPitch === 38) return 1.88
if (CBPitch === 50) return 1.05
if (CBPitch === 76) return 0.62
if (CBPitch === 100) return 0.40
} else if (BBHeight === 55) {
if (CBPitch === 38) return 1.81
if (CBPitch === 50) return 1.03
if (CBPitch === 76) return 0.61
if (CBPitch === 100) return 0.38
} else if (BBHeight === 60) {
if (CBPitch === 38) return 1.75
if (CBPitch === 50) return 1.00
if (CBPitch === 76) return 0.59
if (CBPitch === 100) return 0.36
} else if (BBHeight === 65) {
if (CBPitch === 38) return 1.69
} else if (BBHeight === 70) {
if (CBPitch === 38) return 1.63
} else if (BBHeight === 75) {
if (CBPitch === 38) return 1.56
} else if (BBHeight === 80) {
if (CBPitch === 38) return 1.50
}
}
let m = () => {
if (forge) return m_forge(bearingBarHeight, crossBarPitch)
else return m_pressured(bearingBarHeight, crossBarPitch)
}
const c4 = () => {
if (custom) return 200
else return vehiclesClasses[vehicleClass].c4
}
const d4 = () => {
if (custom) return 200
else return vehiclesClasses[vehicleClass].d4
}
const pointedLoadValue = () => {
if (custom) return req.body.pointedLoadValue
else return vehiclesClasses[vehicleClass].pointedLoad
}
/////////////////////////////////////////////////////////////// computed variables
const MaxM = (((pointedLoadValue() * 1000) * (clearSpan - (d4() / 2))) / 4) * 1.5
const n = (c4() / bearingBarPitch) + m()
const W = () => {
const temp = (((bearingBarThickness * Math.pow(bearingBarHeight, 2)) / 6) * n)
return forge ? temp : (temp * 0.9)
}
const sigma = MaxM / W()
const L = () => {
const temp = (((bearingBarThickness * (Math.pow(bearingBarHeight, 3))) / 12) * n)
return forge ? temp : (temp * 0.9)
}
const D = ((pointedLoadValue() * 1000) / (384 * 210000 * L())) * ((8 * Math.pow(clearSpan, 3)) - (4 * clearSpan * Math.pow(d4(), 2)) + (Math.pow(d4(), 3)))
// console.log('m =' + m())
// console.log('c4 =' + c4())
// console.log('d4 =' + d4())
// console.log('pointedLoadValue =' + pointedLoadValue())
// console.log('MaxM =' + MaxM)
// console.log('n =' + n)
// console.log('W =' + W())
// console.log('sigma =' + sigma)
// console.log('L =' + L())
// console.log('D =' + D)
//////////////////////////////////////////////////////////////// calculate result
const result = {
sigma: null,
sigmaStatus: null,
deflection: null,
deflectionStatus: null
}
if (sigma < 235) {
result.sigma = validationMessages[locale].sigma_ok
result.sigmaStatus = true
} else {
result.sigma = validationMessages[locale].sigma_out_of_range
result.sigmaStatus = false
}
if (D < (clearSpan / 200)) {
result.deflection = validationMessages[locale].deflection_ok
result.deflectionStatus = true
} else {
result.deflection = validationMessages[locale].deflection_out_of_range
result.deflectionStatus = false
}
return result
}
///////// distributed load
function distributedLoad() {
// static variables
const forge = gratingType === 'forge'
const custom = method === 'custom'
// computing distributedLoadValue
const distributedLoadValue = () => {
if (custom) return req.body.distributedLoadValue
else return vehiclesClasses[vehicleClass].distributedLoad
}
////////////////////////////////////////////////////////////////// computed variables
const MaxM = (((distributedLoadValue() * 10) * bearingBarPitch * Math.pow(clearSpan, 2)) / 80000) * 1.5
const W = () => {
const temp = (bearingBarThickness * Math.pow(bearingBarHeight, 2)) / 6
return forge ? temp : (temp * 0.9)
}
const sigma = MaxM / W()
const L = () => {
const temp = (bearingBarThickness * Math.pow(bearingBarHeight, 3)) / 12
return forge ? temp : (temp * 0.9)
}
const D = (5 * distributedLoadValue() * bearingBarPitch * Math.pow(clearSpan, 4)) / (384 * 21000 * L() * Math.pow(10, 4))
////////////////////////////////////////////////////////////////// calculate result
const result = {
sigma: null,
sigmaStatus: null,
deflection: null,
deflectionStatus: null
}
if (sigma < 235) {
result.sigma = validationMessages[locale].sigma_ok
result.sigmaStatus = true
} else {
result.sigma = validationMessages[locale].sigma_out_of_range
result.sigmaStatus = false
}
if (D < (clearSpan / 200)) {
result.deflection = validationMessages[locale].deflection_ok
result.deflectionStatus = true
} else {
result.deflection = validationMessages[locale].deflection_out_of_range
result.deflectionStatus = false
}
return result
}
////////////////////////////////////////////// calculate
if (method === 'custom') {
if (loadType === 'pointedLoad') return res.json(pointedLoad())
else return res.json(distributedLoad())
} else if (method === 'classified') {
if (vehicleClass === 'class1') return res.json(distributedLoad())
else return res.json(pointedLoad())
} else return res.json({message: 'unsupported entry'})
}
]
module.exports.getRelativeValues = [
[
body('gratingType')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].gratingType
})
.bail()
.custom((value, {req}) => {
if (value === 'forge' || value === 'pressured') return true
else Promise.reject(validationMessages[req.body.locale].gratingType_not_supported)
}),
body('crossBarPitch')
.notEmpty().withMessage((value, {req}) => {
return validationMessages[req.body.locale].crossBarPitch
})
.bail()
.custom((value, {req}) => {
if (req.body.gratingType === 'forge') {
if (values.crossBarPitch_forge.includes(Number(value))) return true
else return Promise.reject(validationMessages[req.body.locale].crossBarPitch_not_ok)
} else {
if (values.crossBarPitch_pressured.includes(Number(value))) return true
else return Promise.reject(validationMessages[req.body.locale].crossBarPitch_not_ok)
}
})
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json(errors.mapped())
return res.json(relativeBearingBarHeight(req.body.gratingType, req.body.crossBarPitch))
}
]
module.exports.getValues = [
(req, res) => {
return res.json(values)
}
]
+134 -128
View File
@@ -5,162 +5,168 @@ const jimp = require('jimp')
const fs = require('fs')
const v_m = require('../validation_messages')
// local variables
const imageWidth = 648
const imageHeight = 443
const imageQuality = 100
module.exports.create = [
[
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title),
[
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title),
body('year')
.notEmpty().withMessage(v_m['fa'].required.date)
.bail()
.isNumeric().withMessage(v_m['fa'].format.number)
.bail()
.isLength({min: 4}).withMessage(v_m['fa'].min_char.min4)
.bail()
.isLength({max: 4}).withMessage(v_m['fa'].max_char.max4)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
if (!req.files || !req.files.image) return res.status(422).json({validation: {image: {msg: v_m['fa'].required.image}}})
body('year')
.notEmpty().withMessage(v_m['fa'].required.date)
.bail()
.isNumeric().withMessage(v_m['fa'].format.number)
.bail()
.isLength({min: 4}).withMessage(v_m['fa'].min_char.min4)
.bail()
.isLength({max: 4}).withMessage(v_m['fa'].max_char.max4)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
if (!req.files || !req.files.image) return res.status(422).json({validation: {image: {msg: v_m['fa'].required.image}}})
const fileName = 'history_' + Date.now() + '.' + req.files.image.mimetype.split('/')[1]
const fileName = 'history_' + Date.now() + '.' + req.files.image.mimetype.split('/')[1]
const data = {
image: fileName,
year: Number(req.body.year),
history_details: {
fa: {
title: req.body.fa_title,
caption: req.body.fa_caption
},
en: {
title: req.body.en_title,
caption: req.body.en_caption
}
},
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
const data = {
image: fileName,
year: Number(req.body.year),
history_details: {
fa: {
title: req.body.fa_title,
caption: req.body.fa_caption
},
en: {
title: req.body.en_title,
caption: req.body.en_caption
}
},
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
jimp.read(req.files.image.data)
.then(img => {
img
.resize(380, jimp.AUTO)
.cover(380, 260)
.write(`./static/uploads/images/history/${fileName}`, cb => {
const history = new History(data)
history.save(err => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_save)
})
})
})
.catch(err => {
console.log(err)
})
}
jimp.read(req.files.image.data)
.then(img => {
img
.resize(imageWidth, jimp.AUTO)
.cover(imageWidth, imageHeight)
.quality(imageQuality)
.write(`./static/uploads/images/history/${fileName}`, cb => {
const history = new History(data)
history.save(err => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_save)
})
})
})
.catch(err => {
console.log(err)
})
}
]
module.exports.getAll = [
(req, res) => {
History.find({}).sort({year: 1}).exec((err, data) => {
if (err) console.log(err)
return res.json(data)
})
}
(req, res) => {
History.find({}).sort({year: 1}).exec((err, data) => {
if (err) console.log(err)
return res.json(data)
})
}
]
module.exports.getOne = [
(req, res) => {
History.findById(req.params.id, (err, data) => {
if (err) return res.status(404).json(err)
return res.json(data)
})
}
(req, res) => {
History.findById(req.params.id, (err, data) => {
if (err) return res.status(404).json(err)
return res.json(data)
})
}
]
module.exports.update = [
[
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title),
[
body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title),
body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title),
body('year')
.notEmpty().withMessage(v_m['fa'].required.date)
.bail()
.isNumeric().withMessage(v_m['fa'].format.number)
.bail()
.isLength({min: 4}).withMessage(v_m['fa'].min_char.min4)
.bail()
.isLength({max: 4}).withMessage(v_m['fa'].max_char.max4)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
body('year')
.notEmpty().withMessage(v_m['fa'].required.date)
.bail()
.isNumeric().withMessage(v_m['fa'].format.number)
.bail()
.isLength({min: 4}).withMessage(v_m['fa'].min_char.min4)
.bail()
.isLength({max: 4}).withMessage(v_m['fa'].max_char.max4)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = {
year: Number(req.body.year),
history_details: {
fa: {
title: req.body.fa_title,
caption: req.body.fa_caption
},
en: {
title: req.body.en_title,
caption: req.body.en_caption
}
},
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
const data = {
year: Number(req.body.year),
history_details: {
fa: {
title: req.body.fa_title,
caption: req.body.fa_caption
},
en: {
title: req.body.en_title,
caption: req.body.en_caption
}
},
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
if (req.files && req.files.image) {
let fileName = 'history_' + Date.now() + '.' + req.files.image.mimetype.split('/')[1]
data.image = fileName
jimp.read(req.files.image.data)
.then(img => {
img
.resize(380, jimp.AUTO)
.cover(380, 260)
.write(`./static/uploads/images/history/${fileName}`, cb => {
History.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
fs.unlink(`./static/${oldData.image}`, err => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_save)
})
})
if (req.files && req.files.image) {
let fileName = 'history_' + Date.now() + '.' + req.files.image.mimetype.split('/')[1]
data.image = fileName
jimp.read(req.files.image.data)
.then(img => {
img
.resize(imageWidth, jimp.AUTO)
.cover(imageWidth, imageHeight)
.quality(imageQuality)
.write(`./static/uploads/images/history/${fileName}`, cb => {
History.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
fs.unlink(`./static/${oldData.image}`, err => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_save)
})
})
.catch(err => {
console.log(err)
})
} else {
History.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_save)
})
})
})
}
}
.catch(err => {
console.log(err)
})
} else {
History.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_save)
})
}
}
]
module.exports.delete = [
(req, res) => {
History.findByIdAndDelete(req.params.id, (err, data) => {
if (err) console.log(err)
fs.unlink(`./static/${data.image}`, err => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_remove)
})
(req, res) => {
History.findByIdAndDelete(req.params.id, (err, data) => {
if (err) console.log(err)
fs.unlink(`./static/${data.image}`, err => {
if (err) console.log(err)
return res.json(v_m['fa'].response.success_remove)
})
}
})
}
]
+38 -36
View File
@@ -4,47 +4,49 @@ const v_m = require('../validation_messages')
const fs = require('fs')
module.exports.create = [
(req, res) => {
if (!req.files || !req.files.pdf) return res.status(422).json({validation: {pdf: {msg: v_m['fa'].required.file}}})
if (req.files.pdf.mimetype.split('/')[1] !== 'pdf') return res.status(422).json({validation: {pdf: {msg: v_m['fa'].file_types.pdf}}})
(req, res) => {
if (!req.files || !req.files.pdf) return res.status(422).json({validation: {pdf: {msg: v_m['fa'].required.file}}})
if (req.files.pdf.mimetype.split('/')[1] !== 'pdf') return res.status(422).json({validation: {pdf: {msg: v_m['fa'].file_types.pdf}}})
MainCatalog.find({}, (err, catalogs) => {
if (catalogs.length) {
let firstFile = catalogs[0]
fs.unlink(`./static/${firstFile.file}`, err => {
if (err) console.log(err)
firstFile.file = req.files.pdf.name
firstFile.created_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
firstFile.save((err1, data) => {
if (err1) console.log(err1)
req.files.pdf.mv(`./static/uploads/pdf/${req.files.pdf.name}`)
return res.json(firstFile)
})
MainCatalog.find({}, (err, catalogs) => {
if (catalogs.length) {
let firstFile = catalogs[0]
})
} else {
new MainCatalog({
file: req.files.pdf.name,
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}).save((err, data) => {
if (err) console.log(err)
req.files.pdf.mv(`./static/uploads/pdf/${req.files.pdf.name}`)
return res.json(data)
})
}
})
if (firstFile.file[req.body.locale]) fs.unlink(`./static/${firstFile.file[req.body.locale]}`, err => {
if (err) console.log(err)
})
}
firstFile.file[req.body.locale] = req.body.locale + '_' + req.files.pdf.name
firstFile.updated_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
firstFile.save((err1, data) => {
if (err1) console.log(err1)
req.files.pdf.mv(`./static/uploads/pdf/${req.body.locale}_${req.files.pdf.name}`)
return res.json(firstFile)
})
} else {
const data = {created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss'), file: {}}
data.file[req.body.locale] = req.body.locale + '_' + req.files.pdf.name
new MainCatalog(data).save((err, data) => {
if (err) console.log(err)
req.files.pdf.mv(`./static/uploads/pdf/${req.body.locale}_${req.files.pdf.name}`)
return res.json(data)
})
}
})
}
]
module.exports.get = [
(req, res) => {
MainCatalog.find({}, (err, catalog) => {
if (err) console.log(err)
if (catalog.length) return res.json(catalog[0])
else return res.json({})
})
}
(req, res) => {
MainCatalog.find({}, (err, catalog) => {
if (err) console.log(err)
if (catalog.length) return res.json(catalog[0])
else return res.json({})
})
}
]
+76 -75
View File
@@ -5,101 +5,102 @@ const dateformat = require('dateformat')
const v_m = require('../validation_messages')
module.exports.create = [
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title),
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title),
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
],
(req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = {
category_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
},
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
const data = {
category_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
},
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
const category = new ProductCategory(data)
category.save(err => {
if (err) return res.status(500).json({message: err})
return res.json({message: v_m['fa'].response.success_save})
})
}
const category = new ProductCategory(data)
category.save(err => {
if (err) return res.status(500).json({message: err})
return res.json({message: v_m['fa'].response.success_save})
})
}
]
module.exports.getAll = [
(req, res) => {
ProductCategory.find({}, (err, categories) => {
if (err) return res.status(500).json({message: err})
return res.json(categories)
})
}
(req, res) => {
ProductCategory.find({}, (err, categories) => {
if (err) return res.status(500).json({message: err})
return res.json(categories)
})
}
]
module.exports.getOne = [
(req, res) => {
ProductCategory.findById(req.params.id, (err, category) => {
if (err) console.log(err)
return res.json(category)
})
}
(req, res) => {
ProductCategory.findById(req.params.id, (err, category) => {
if (err) console.log(err)
return res.json(category)
})
}
]
module.exports.update = [
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title),
[
body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title),
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
],
(req, res) => {
// check validation results
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title)
],
(req, res) => {
// check validation results
const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = {
category_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
}
}
const data = {
category_details: {
fa: {
name: req.body.fa_name
},
en: {
name: req.body.en_name
}
},
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
ProductCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_save})
})
}
ProductCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_save})
})
}
]
module.exports.delete = [
(req, res) => {
Product.findOne({category: req.params.id}, (err, product) => {
if (err) console.log(err)
if (product) return res.status(400).json({message: 'این دسته بندی دارای محصول است.'})
else {
ProductCategory.findByIdAndDelete(req.params.id, (err, category) => {
if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_remove})
})
}
})
}
(req, res) => {
Product.findOne({category: req.params.id}, (err, product) => {
if (err) console.log(err)
if (product) return res.status(400).json({message: 'این دسته بندی دارای محصول است.'})
else {
ProductCategory.findByIdAndDelete(req.params.id, (err, category) => {
if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_remove})
})
}
})
}
]
File diff suppressed because it is too large Load Diff
+9 -5
View File
@@ -1,15 +1,19 @@
const mongoose = require('mongoose')
function catalog(pdf) {
return '/uploads/pdf/' + pdf
if (pdf) return '/uploads/pdf/' + pdf
}
const MainCatalogSchema = mongoose.Schema({
file: {type: String, get: catalog},
created_at: String
file: {
fa: {type: String, get: catalog},
en: {type: String, get: catalog}
},
created_at: String,
updated_at: String
}, {
toObject: {getters: true},
toJSON: {getters: true}
toObject: {getters: true},
toJSON: {getters: true}
})
module.exports = mongoose.model('MainCatalog', MainCatalogSchema)
+68 -63
View File
@@ -1,84 +1,89 @@
const mongoose = require('mongoose')
function productImage(img) {
return '/uploads/images/products/' + img
if (img) return '/uploads/images/products/' + img
}
function productPDF(file) {
return '/uploads/pdf/' + file
if (file) return '/uploads/pdf/' + file
}
const ProductImageSchema = mongoose.Schema({
image: {type: String, get: productImage},
created_at: String
image: {type: String, get: productImage},
created_at: String
}, {
toObject: {getters: true},
toJSON: {getters: true}
toObject: {getters: true},
toJSON: {getters: true}
})
const ProductPDFSchema = mongoose.Schema({
file: {type: String, get: productPDF},
pdf_details: {
fa: {
name: String
},
en: {
name: String
}
},
created_at: String
file: {
fa: {type: String, get: productPDF},
en: {type: String, get: productPDF}
},
pdf_details: {
fa: {
name: String
},
en: {
name: String
}
},
created_at: String
}, {
toObject: {getters: true},
toJSON: {getters: true}
toObject: {getters: true},
toJSON: {getters: true}
})
const ProductSchema = mongoose.Schema({
cover: {type: String, get: productImage},
images: [ProductImageSchema],
more_section_image1: {type: String, get: productImage},
more_section_image2: {type: String, get: productImage},
render_image1: {type: String, get: productImage},
render_image2: {type: String, get: productImage},
chart_image: {type: String, get: productImage},
pdf_files: [ProductPDFSchema],
category: String,
more_section: {type: Boolean, default: true},
download_section: {type: Boolean, default: true},
product_details: {
fa: {
name: String,
short_description: String,
page_title: String,
page_description: String,
more_title1: String,
more_description1: String,
more_title2: String,
more_description2: String,
render_caption1: String,
render_caption2: String,
chart_title: String,
chart_description: String
},
en: {
name: String,
short_description: String,
page_title: String,
page_description: String,
more_title1: String,
more_description1: String,
more_title2: String,
more_description2: String,
render_caption1: String,
render_caption2: String,
chart_title: String,
chart_description: String
}
},
created_at: String,
updated_at: String
cover: {type: String, get: productImage},
thumb: {type: String, get: productImage},
images: [ProductImageSchema],
more_section_image1: {type: String, get: productImage},
more_section_image2: {type: String, get: productImage},
render_image1: {type: String, get: productImage},
render_image2: {type: String, get: productImage},
chart_image: {type: String, get: productImage},
pdf_files: [ProductPDFSchema],
category: String,
more_section: {type: Boolean, default: true},
download_section: {type: Boolean, default: true},
favorite: {type: Boolean, default: false},
product_details: {
fa: {
name: String,
short_description: String,
page_title: String,
page_description: String,
more_title1: String,
more_description1: String,
more_title2: String,
more_description2: String,
render_caption1: String,
render_caption2: String,
chart_title: String,
chart_description: String
},
en: {
name: String,
short_description: String,
page_title: String,
page_description: String,
more_title1: String,
more_description1: String,
more_title2: String,
more_description2: String,
render_caption1: String,
render_caption2: String,
chart_title: String,
chart_description: String
}
},
created_at: String,
updated_at: String
}, {
toObject: {getters: true},
toJSON: {getters: true}
toObject: {getters: true},
toJSON: {getters: true}
})
+7 -1
View File
@@ -12,6 +12,7 @@ const contactPageController = require('../controllers/contactPageController')
const contactUsReasonController = require('../controllers/contactUsReasonController')
const mainCatalogController = require('../controllers/mainCatalogController')
const historyController = require('../controllers/historyController')
const calculationModule = require('../controllers/calculationModule')
/////////////////////////////////////////////////////////// routes
//////////////// slider
@@ -31,7 +32,7 @@ router.get('/productCategories', productCategoryController.getAll)
router.get('/productCategories/:id', productCategoryController.getOne)
//////////////// products
router.get('/products/:category', productController.getAllProductsByCategory)
router.get('/favoriteProducts', productController.getFavoriteProducts)
router.get('/products/', productController.getAllProducts)
router.get('/product/:id', productController.getOneProduct)
@@ -51,4 +52,9 @@ router.get('/catalog', mainCatalogController.get)
router.get('/history', historyController.getAll)
router.get('/history/:id', historyController.getOne)
//////////////// calculation
router.get('/calculation/values', calculationModule.getValues)
router.post('/calculation/relativeValues', calculationModule.getRelativeValues)
router.post('/calculate', calculationModule.calculate)
module.exports = router
+30 -7
View File
@@ -127,7 +127,7 @@ $panelBg: #fff;
padding: 0 15px;
position: fixed;
top: 56px;
left: 15px;
left: 0;
z-index: 5;
h2 {
@@ -177,10 +177,11 @@ $panelBg: #fff;
}
.admin--sidebar {
min-height: calc(100vh - 55px);
height: calc(100vh - 55px);
background: $sidebar;
flex-basis: 300px;
border-left: 1px solid $borders;
overflow: auto;
ul {
width: 100%;
@@ -231,6 +232,23 @@ $panelBg: #fff;
.admin-user {
padding: 20px 15px;
color: $usernameColor;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
.el-avatar {
display: block;
width: 50px;
height: 50px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
h2 {
font-size: 25px !important;
@@ -254,6 +272,11 @@ $panelBg: #fff;
}
}
}
.sidebar--content {
height: 100%;
overflow: auto;
}
}
.admin--header {
@@ -320,6 +343,11 @@ $panelBg: #fff;
text-align: center;
}
.err {
color: red;
font-size: 13px;
}
}
pre {
@@ -382,11 +410,6 @@ html:lang(fa) {
margin-top: 50px;
}
.err {
color: red;
font-size: 13px;
}
.el-upload__input {
display: none !important;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 KiB

After

Width:  |  Height:  |  Size: 286 KiB

Before

Width:  |  Height:  |  Size: 640 KiB

After

Width:  |  Height:  |  Size: 640 KiB

+74
View File
@@ -0,0 +1,74 @@
.ck-content {
width: 100%;
direction: rtl;
text-align: right;
&:lang(en) {
direction: ltr;
text-align: left;
}
a {
display: inline-block;
color: blue;
}
p, a, span, b, ul, li, em, h1, h2, h3, h4, h5, h6, strong {
font-family: inherit, sans-serif;
direction: unset;
text-align: unset;
&:lang(en) {
font-family: inherit;
direction: unset;
text-align: unset;
}
&[dir="ltr"] {
direction: ltr;
text-align: left;
p, a, span, b, ul, li, em, h1, h2, h3, h4, h5, h6, strong {
direction: ltr;
text-align: left;
}
}
&[dir="rtl"] {
direction: rtl;
text-align: right;
p, a, span, b, ul, li, em, h1, h2, h3, h4, h5, h6, strong {
direction: rtl;
text-align: right;
}
}
}
p {
line-height: 1.6em;
}
h1, h2, h3, h4, h5, h6 {
line-height: 1.3em;
}
li {
margin-bottom: 15px;
line-height: 1.6em;
}
ol {
list-style: decimal;
list-style-position: inside;
}
ul {
list-style: disc;
list-style-position: inside;
}
img {
max-width: 100%!important;
}
}
+16 -6
View File
@@ -6,12 +6,6 @@
url("../fonts/sahel/Sahel-FD.woff") format('woff');
}
@font-face {
font-family: 'sahel-bold';
src: url("../fonts/sahel/Sahel-Bold-FD.eot") format('embedded-opentype'),
url("../fonts/sahel/Sahel-Bold-FD.ttf") format('truetype'),
url("../fonts/sahel/Sahel-Bold-FD.woff") format('woff');
}
@font-face {
font-family: 'sahel-black';
@@ -20,6 +14,22 @@
url("../fonts/sahel/Sahel-Black-FD.woff") format('woff');
}
////// sahel with latin
@font-face {
font-family: 'sahel-LD';
src: url("../fonts/sahelWithLatin/regular/Sahel.eot") format('embedded-opentype'),
url("../fonts/sahelWithLatin/regular/Sahel.ttf") format('truetype'),
url("../fonts/sahelWithLatin/regular/Sahel.woff") format('woff');
}
@font-face {
font-family: 'sahel-black-LD';
src: url("../fonts/sahelWithLatin/black/Sahel-Black.eot") format('embedded-opentype'),
url("../fonts/sahelWithLatin/black/Sahel-Black.ttf") format('truetype'),
url("../fonts/sahelWithLatin/black/Sahel-Black.woff") format('woff');
}
////// diodrum
@font-face {
font-family: 'diodrum';
+25 -2
View File
@@ -11,8 +11,8 @@ body {
}
}
p, a, span, b {
font-family: 'sahel';
p, a, span, b, label, strong, small, li {
font-family: 'sahel', 'diodrum', sans-serif;
color: rgba(0, 0, 0, 0.7);
line-height: 1.6em;
@@ -67,6 +67,24 @@ section {
padding: 0 0 100px;
}
.latin-digits {
p, a, span, b, label, strong, small, li, td, tr, th {
font-family: 'sahel-LD', 'diodrum', sans-serif;
&:lang(en) {
font-family: 'diodrum';
}
}
h1, h2, h3, h4, h5, h6 {
font-family: 'sahel-black-LD';
&:lang(en) {
font-family: 'diodrum-bold';
}
}
}
@keyframes loading {
0% {
@include transform(rotateZ(0));
@@ -168,6 +186,11 @@ section {
display: flex;
align-items: stretch;
background: $darkGray;
direction: ltr;
&:lang(en) {
direction: rtl;
}
.catalog-download {
display: block;
+245 -72
View File
@@ -341,7 +341,7 @@
.hero {
.bg {
background-image: url("../img/about/about-hero.jpg");
background-image: url("../img/services/hero.jpg");
}
}
@@ -557,7 +557,7 @@
.hero {
.bg {
background-image: url('../img/services/services-hero.jpg');
background-image: url('../img/services/hero.jpg');
}
}
@@ -639,7 +639,7 @@
.products--page {
.hero {
.bg {
background-image: url('../img/products/products-hero.jpg');
background-image: url('../img/products/hero.jpg');
}
}
@@ -760,7 +760,6 @@
///////////////////////////// products page
.product-details--page {
.hero {
.bg {
background-image: url('../img/products/products-hero.jpg');
@@ -782,14 +781,7 @@
}
img {
width: 50%;
@media (max-width: 1200px) {
width: 80%;
}
@media (max-width: 992px) {
width: 100%;
}
width: 100%;
}
}
@@ -818,20 +810,28 @@
}
#images {
margin-top: 250px;
margin-top: 80px;
img {
width: 60%;
min-height: 100px;
object-fit: cover;
margin: 0 auto;
cursor: pointer;
border: 3px solid transparent;
@extend %defaultTransition;
&.selected {
border: 3px solid $red;
}
}
}
}
}
.s2 {
margin-top: 100px;
margin-top: 200px;
.parts {
margin-top: 100px;
@@ -877,6 +877,10 @@
&.p3 {
text-align: center;
img {
width: 100%;
}
}
&.p4 {
@@ -1117,8 +1121,16 @@
text-align: right;
margin-bottom: 30px;
span {
font-family: 'sahel', sans-serif;
}
&:lang(en) {
text-align: left;
span {
font-family: 'diodrum', sans-serif;
}
}
.category {
@@ -1178,6 +1190,14 @@
text-align: center;
margin-bottom: 80px;
span {
font-family: 'sahel', sans-serif;
&:lang(en) {
font-family: 'diodrum', sans-serif;
}
}
.category {
display: block;
margin-bottom: 10px;
@@ -1212,52 +1232,6 @@
}
}
}
.content {
direction: rtl;
text-align: right;
&:lang(en) {
direction: ltr;
text-align: left;
}
a {
color: blue;
}
p, a, span, b, ul, li, em, h1, h2, h3, h4, h5, h6, strong {
font-family: 'sahel', sans-serif;
direction: unset;
text-align: unset;
&:lang(en) {
font-family: 'diodrum';
direction: unset;
text-align: unset;
}
&[dir="ltr"] {
direction: ltr;
text-align: left;
p, a, span, b, ul, li, em, h1, h2, h3, h4, h5, h6, strong {
direction: ltr;
text-align: left;
}
}
&[dir="rtl"] {
direction: rtl;
text-align: right;
p, a, span, b, ul, li, em, h1, h2, h3, h4, h5, h6, strong {
direction: rtl;
text-align: right;
}
}
}
}
}
.s2 {
@@ -1290,13 +1264,31 @@
li {
margin-bottom: 30px;
i {
color: $red;
margin-left: 5px;
a {
@extend %defaultTransition;
&:lang(en) {
margin-left: 0;
margin-right: 5px;
&:hover {
color: $theme;
b {
color: $theme;
}
}
i {
color: $red;
margin-left: 5px;
&:lang(en) {
margin-left: 0;
margin-right: 5px;
}
}
.phone-number {
display: inline-block;
direction: ltr !important;
text-align: left;
}
}
}
@@ -1404,8 +1396,14 @@
list-style: decimal;
list-style-position: outside;
p {
a {
direction: ltr;
color: $theme;
@extend %defaultTransition;
&:hover {
color: $red;
}
}
}
}
@@ -1421,6 +1419,17 @@
}
}
&.gUsage {
img {
display: block;
margin-top: 50px;
margin-left: auto;
margin-right: auto;
width: 800px;
max-width: 100%;
}
}
h2 {
margin-top: 80px;
margin-bottom: 30px;
@@ -1482,29 +1491,48 @@
.s2 {
.app {
$appLayoutPadding: 55px;
@include transition(0.1s);
.appTitle {
text-align: center;
.title {
font-size: 30px;
@media (max-width: 1400px) {
font-size: 25px;
}
}
}
.appMethod {
text-align: center;
margin-bottom: 50px;
background: $red;
background: $theme;
padding: 15px;
.txt {
display: inline-block;
margin: 0 10px 10px;
}
span {
color: #fff;
}
.el-radio-button__orig-radio:checked + .el-radio-button__inner {
background-color: $darkGray;
border-color: $darkGray;
border-color: #fff;
@include boxShadow(-1px 0 0 0 $darkGray);
}
.el-radio-button .el-radio-button__inner {
color: $red;
color: $theme;
@extend %userSelect;
@media (max-width: 530px) {
font-size: 12px;
}
}
.el-radio-button.is-active .el-radio-button__inner {
@@ -1513,8 +1541,8 @@
}
.appLayout {
padding: 55px;
background: $red;
padding: $appLayoutPadding;
background: $theme;
height: 100%;
@include boxSizing(border-box);
@@ -1608,6 +1636,10 @@
color: $darkGray;
}
}
.err {
color: $red;
}
}
.el-input {
@@ -1616,6 +1648,35 @@
//@media (max-width: 600px) {
// width: 100%;
//}
input {
font-family: 'sahel', 'diodrum', sans-serif;
&:lang(en) {
font-family: 'diodrum', sans-serif;
}
&::placeholder {
font-family: 'sahel';
&:lang(en) {
font-family: 'diodrum';
}
}
}
.el-input__suffix {
right: auto;
left: 5px;
&:lang(en) {
right: 5px;
left: auto;
}
.el-input__icon {
color: #000;
}
}
}
.el-select {
@@ -1630,6 +1691,118 @@
margin-left: 20px;
}
}
.appResult {
background: lightgray;
padding-left: $appLayoutPadding;
padding-right: $appLayoutPadding;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
opacity: 0;
height: 0;
overflow: hidden;
.success {
color: #67C23A;
}
.failure {
color: $red;
}
@keyframes waiting {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
p {
font-size: 20px;
font-weight: bold;
}
.waiting {
@include animation(waiting 0.7s alternate-reverse infinite);
}
}
}
}
.s3 {
.notice {
color: red;
font-size: 14px;
display: none;
@media (max-width: 992px) {
display: block;
}
}
.tableBox {
width: 100%;
overflow: auto;
table {
width: 100%;
min-width: 960px;
border: 1px solid rgba(#000, 1);
thead {
background: $theme;
color: #fff;
th {
padding: 20px;
font-family: 'sahel-LD', 'diodrum', sans-serif;
direction: ltr;
&.middle {
border-left: 2px solid rgba(#fff, 0.4) !important;
border-right: 2px solid rgba(#fff, 0.4) !important;
}
}
}
tbody {
background: rgba($theme, 0.2);
color: #000;
tr {
line-height: 1.3em;
td {
border: 1px solid rgba(#000, 1);
padding: 20px;
font-family: 'sahel-LD', 'diodrum', sans-serif;
direction: ltr;
text-align: center;
&:last-child {
direction: ltr !important;
}
}
&.odd {
background: rgba(#000, 0.1);
}
}
}
}
&.vehicles {
}
&.forklifts {
margin-top: 50px;
}
}
}
}
+1
View File
@@ -1,3 +1,4 @@
@import "CKEditorStyle";
@import "variables";
@import "mixins";
@import "extentions";
+42 -47
View File
@@ -1,53 +1,48 @@
<template>
<footer class="footer">
<div class="container">
<div class="row">
<div class="col-12 col-md-8 mb-3 mb-md-0 links">
<logo/>
<div class="box">
<p><b>{{staticData.t1}}</b> <span>{{staticData.address}}</span></p>
<!-- <hr>-->
<p class="red">
<b>{{staticData.t2}}</b> <a :href="'tel:' + staticData.fax">{{staticData.tell}}</a>
&nbsp &nbsp - &nbsp &nbsp
<b>{{staticData.t3}}</b> <a :href="'tel:' + staticData.fax">{{staticData.fax}}</a>
</p>
</div>
</div>
<div class="col-12 col-md-4 social">
<ul class="social-links">
<li>
<a href="" target="_blank">
<em class="fab fa-facebook-f"></em>
</a>
</li>
<li>
<a href="" target="_blank">
<em class="fab fa-twitter"></em>
</a>
</li>
<li>
<a href="" target="_blank">
<em class="fab fa-telegram-plane"></em>
</a>
</li>
</ul>
<p>{{staticData.t5}}</p>
<p class="blue"><b>{{staticData.t4}}</b> <a :href="'mailto:' + staticData.email">{{staticData.email}}</a></p>
</div>
</div>
</div>
<div class="footer-bar"></div>
</footer>
<footer class="footer">
<div class="container">
<div class="row">
<div class="col-12 col-md-8 mb-3 mb-md-0 links">
<logo/>
<div class="box">
<p><b>{{ staticData.t1 }}</b> <span>{{ $store.state.global.address[$route.params.lang] }}</span></p>
<!-- <hr>-->
<p class="red">
<b>{{ staticData.t2 }}</b> <a :href="'tel:' + $store.state.global.tell">{{ $store.state.global.tell_view }}</a>
&nbsp &nbsp - &nbsp &nbsp
<b>{{ staticData.t3 }}</b> <a :href="'tel:' + $store.state.global.fax">{{ $store.state.global.fax_view }}</a>
</p>
</div>
</div>
<div class="col-12 col-md-4 social">
<ul class="social-links">
<li>
<a :href="$store.state.global.instagram_url" target="_blank">
<i class="fab fa-instagram"></i>
</a>
</li>
<li>
<a :href="$store.state.global.linkedin_url" target="_blank">
<i class="fab fa-linkedin-in"></i>
</a>
</li>
</ul>
<p>{{ staticData.t5 }}</p>
<p class="blue"><b>{{ staticData.t4 }}</b> <a :href="'mailto:' + $store.state.global.email">{{ $store.state.global.email }}</a></p>
</div>
</div>
</div>
<div class="footer-bar"></div>
</footer>
</template>
<script>
export default {
computed: {
staticData() {
return this.$store.state.staticData.footer[this.$route.params.lang]
}
}
}
export default {
computed: {
staticData() {
return this.$store.state.staticData.footer[this.$route.params.lang]
}
}
}
</script>
+43 -48
View File
@@ -1,53 +1,48 @@
<template>
<footer class="footer footer--home">
<div class="container">
<div class="row">
<div class="xol-12 col-md-8 mb-5 mb-md-0 links">
<div class="logo">
<logo/>
<span>{{staticData.t6}}</span>
</div>
<div class="box">
<p><b>{{staticData.t1}}</b> <span>{{staticData.address}}</span></p>
<hr>
<p class="red"><b>{{staticData.t2}}</b> <a :href="'tel:' + staticData.fax">{{staticData.tell}}</a></p>
<p class="red"><b>{{staticData.t3}}</b> <a :href="'tel:' + staticData.fax">{{staticData.fax}}</a></p>
<ul class="social-links red">
<li>
<a href="" target="_blank">
<em class="fab fa-facebook-f"></em>
</a>
</li>
<li>
<a href="" target="_blank">
<em class="fab fa-twitter"></em>
</a>
</li>
<li>
<a href="" target="_blank">
<em class="fab fa-telegram-plane"></em>
</a>
</li>
</ul>
<p class="blue"><b>{{staticData.t4}}</b> <a :href="'mailto:' + staticData.email">{{staticData.email}}</a></p>
</div>
</div>
<div class="xol-12 col-md-4 map">
<img src="~/assets/img/footer-map.jpg" alt="">
<p>{{staticData.t5}}</p>
</div>
</div>
</div>
<div class="footer-bar"></div>
</footer>
<footer class="footer footer--home">
<div class="container">
<div class="row">
<div class="xol-12 col-md-8 mb-5 mb-md-0 links">
<div class="logo">
<logo/>
<span>{{ staticData.t6 }}</span>
</div>
<div class="box">
<p><b>{{ staticData.t1 }}</b> <span>{{ $store.state.global.address[$route.params.lang] }}</span></p>
<hr>
<p class="red"><b>{{ staticData.t2 }}</b> <a :href="'tel:' + $store.state.global.tell">{{ $store.state.global.tell_view }}</a></p>
<p class="red"><b>{{ staticData.t3 }}</b> <a :href="'tel:' + $store.state.global.fax">{{ $store.state.global.fax_view }}</a></p>
<ul class="social-links red">
<li>
<a :href="$store.state.global.instagram_url" target="_blank">
<i class="fab fa-instagram"></i>
</a>
</li>
<li>
<a :href="$store.state.global.linkedin_url" target="_blank">
<i class="fab fa-linkedin-in"></i>
</a>
</li>
</ul>
<p class="blue"><b>{{ staticData.t4 }}</b> <a :href="'mailto:' + $store.state.global.email">{{ $store.state.global.email }}</a></p>
</div>
</div>
<div class="xol-12 col-md-4 map">
<img src="~/assets/img/footer-map.jpg" alt="">
<p>{{ staticData.t5 }}</p>
</div>
</div>
</div>
<div class="footer-bar"></div>
</footer>
</template>
<script>
export default {
computed: {
staticData() {
return this.$store.state.staticData.footer[this.$route.params.lang]
}
}
}
export default {
computed: {
staticData() {
return this.$store.state.staticData.footer[this.$route.params.lang]
}
}
}
</script>
+167 -167
View File
@@ -1,176 +1,176 @@
<template>
<header class="header">
<div class="lang-bar">
<a :href="catalog.file" target="_blank" class="catalog-download">
<span>{{staticData.catalog}}</span>
<span>&nbsp;</span>
<i class="fas fa-download"></i>
</a>
<div class="dropdown" @mouseenter="drop" @mouseleave="drop">
<div class="title">
<p class="current-lang">
<span>FA / EN</span>
<i class="fas fa-sort-down"></i>
</p>
</div>
<div class="dropMenu">
<div class="drop-item">
<nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'fa'}}">FA</nuxt-link>
</div>
<div class="drop-item">
<nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'en'}}">EN</nuxt-link>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<nav class="row align-items-center">
<!-- desktop -->
<div class="col-12 d-none d-md-block links">
<div class="container-fluid">
<ul class="row justify-content-start">
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a class="logo">
<Logo/>
</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.home}}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-about',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.about}}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-services',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.services}}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" tag="li" class="">
<a>{{staticData.products}}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-projects',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.projects}}</a>
</nuxt-link>
<li class="tech_info" @mouseenter="tech_info" @mouseleave="tech_info"
:class="$route.name === 'lang-tech-gDesign' ||
<header class="header">
<div class="lang-bar">
<a v-if="catalog && catalog.file" :href="catalog.file[$route.params.lang]" target="_blank" class="catalog-download">
<span>{{ staticData.catalog }}</span>
<span>&nbsp;</span>
<i class="fas fa-download"></i>
</a>
<div class="dropdown" @mouseenter="drop" @mouseleave="drop">
<div class="title">
<p class="current-lang">
<span>FA / EN</span>
<i class="fas fa-sort-down"></i>
</p>
</div>
<div class="dropMenu">
<div class="drop-item">
<nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'fa'}}">FA</nuxt-link>
</div>
<div class="drop-item">
<nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'en'}}">EN</nuxt-link>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<nav class="row align-items-center">
<!-- desktop -->
<div class="col-12 d-none d-md-block links">
<div class="container-fluid">
<ul class="row justify-content-start">
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a class="logo">
<Logo/>
</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{ staticData.home }}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-about',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{ staticData.about }}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-services',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{ staticData.services }}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" tag="li" class="">
<a>{{ staticData.products }}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-projects',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{ staticData.projects }}</a>
</nuxt-link>
<li class="tech_info" @mouseenter="tech_info" @mouseleave="tech_info"
:class="$route.name === 'lang-tech-gDesign' ||
$route.name === 'lang-tech-gStandard' ||
$route.name === 'lang-tech-gTech' ||
$route.name === 'lang-tech-gUsage' ? 'active' : null">
<a>{{staticData.tech_info}}</a>
<div class="drop-down">
<ul>
<li :class="$route.name === 'lang-tech-gTech' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gTech',params: {lang: $route.params.lang}}">{{staticData.ti_1}}</nuxt-link>
</li>
<li :class="$route.name === 'lang-tech-gStandard' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gStandard',params: {lang: $route.params.lang}}">{{staticData.ti_2}}</nuxt-link>
</li>
<li :class="$route.name === 'lang-tech-gDesign' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gDesign',params: {lang: $route.params.lang}}">{{staticData.ti_3}}</nuxt-link>
</li>
<li :class="$route.name === 'lang-tech-gUsage' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gUsage',params: {lang: $route.params.lang}}">{{staticData.ti_4}}</nuxt-link>
</li>
</ul>
</div>
</li>
<nuxt-link :to="{name: 'lang-blog',params: {lang: $route.params.lang}}" tag="li" class="">
<a>{{staticData.blog}}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-contact',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.contact}}</a>
</nuxt-link>
</ul>
</div>
</div>
<!-- mobile -->
<div class="col-12 d-md-none links mobile">
<div class="container-fluid">
<ul class="row">
<li class="col">
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" exact class="logo">
<Logo/>
</nuxt-link>
</li>
<li class="col menu">
<div id="menuBtn" @click="offCanvas">
<div class="bars b1"></div>
<div class="bars b2"></div>
<div class="bars b3"></div>
</div>
</li>
</ul>
</div>
</div>
</nav>
</div>
</header>
<a>{{ staticData.tech_info }}</a>
<div class="drop-down">
<ul>
<li :class="$route.name === 'lang-tech-gTech' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gTech',params: {lang: $route.params.lang}}">{{ staticData.ti_1 }}</nuxt-link>
</li>
<li :class="$route.name === 'lang-tech-gStandard' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gStandard',params: {lang: $route.params.lang}}">{{ staticData.ti_2 }}</nuxt-link>
</li>
<li :class="$route.name === 'lang-tech-gDesign' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gDesign',params: {lang: $route.params.lang}}">{{ staticData.ti_3 }}</nuxt-link>
</li>
<li :class="$route.name === 'lang-tech-gUsage' ? 'sub-menu-active' : null">
<nuxt-link :to="{name: 'lang-tech-gUsage',params: {lang: $route.params.lang}}">{{ staticData.ti_4 }}</nuxt-link>
</li>
</ul>
</div>
</li>
<nuxt-link :to="{name: 'lang-blog',params: {lang: $route.params.lang}}" tag="li" class="">
<a>{{ staticData.blog }}</a>
</nuxt-link>
<nuxt-link :to="{name: 'lang-contact',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{ staticData.contact }}</a>
</nuxt-link>
</ul>
</div>
</div>
<!-- mobile -->
<div class="col-12 d-md-none links mobile">
<div class="container-fluid">
<ul class="row">
<li class="col">
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" exact class="logo">
<Logo/>
</nuxt-link>
</li>
<li class="col menu">
<div id="menuBtn" @click="offCanvas">
<div class="bars b1"></div>
<div class="bars b2"></div>
<div class="bars b3"></div>
</div>
</li>
</ul>
</div>
</div>
</nav>
</div>
</header>
</template>
<script>
export default {
data() {
return {
catalog: null
}
},
async fetch() {
let catalog = await this.$axios.get('/api/public/catalog')
this.catalog = catalog.data
},
computed: {
staticData() {
return this.$store.state.staticData.header[this.$route.params.lang]
},
offCanvasLiTL() {
if (process.server) return null
else return this.$gsap.timeline({delay: 0.3, paused: true})
.fromTo($('.offCanvas ul li'), {
x: this.$route.params.lang === 'fa' ? 10 : -10,
opacity: 0
}, {
x: 0,
opacity: 1,
duration: 0.4,
stagger: 0.03
})
}
},
methods: {
drop() {
$('.dropdown').toggleClass('dropdown-active')
},
tech_info() {
const el = $('.tech_info .drop-down')
if (el.height() === 0) {
el.css({height: $('.tech_info .drop-down ul').height()})
} else {
el.css({height: 0})
}
},
offCanvas() {
if ($('.offCanvas').hasClass('active')) this.offCanvasLiTL.reverse()
else this.offCanvasLiTL.play()
$('#menuBtn').toggleClass('close')
$('.offCanvas').toggleClass('active')
$('body').toggleClass('offCanvas-active')
}
},
mounted() {
/////////////////////////////////////////////////////////// small header
$(window).scroll(function (e) {
if ($(window).scrollTop() > 50) {
$('.header,.offCanvas').addClass('header-small')
} else {
$('.header,.offCanvas').removeClass('header-small')
}
})
/////////////////////////////////// offCanvas menu links
$('.offCanvas ul li').click(() => {
this.offCanvas()
})
$('.header .lang-bar a').click(() => {
if ($('.offCanvas').hasClass('active')) this.offCanvas()
})
export default {
data() {
return {
catalog: null
}
},
async fetch() {
let catalog = await this.$axios.get('/api/public/catalog')
this.catalog = catalog.data
},
computed: {
staticData() {
return this.$store.state.staticData.header[this.$route.params.lang]
},
offCanvasLiTL() {
if (process.server) return null
else return this.$gsap.timeline({delay: 0.3, paused: true})
.fromTo($('.offCanvas ul li'), {
x: this.$route.params.lang === 'fa' ? 10 : -10,
opacity: 0
}, {
x: 0,
opacity: 1,
duration: 0.4,
stagger: 0.03
})
}
},
methods: {
drop() {
$('.dropdown').toggleClass('dropdown-active')
},
tech_info() {
const el = $('.tech_info .drop-down')
if (el.height() === 0) {
el.css({height: $('.tech_info .drop-down ul').height()})
} else {
el.css({height: 0})
}
}
},
offCanvas() {
if ($('.offCanvas').hasClass('active')) this.offCanvasLiTL.reverse()
else this.offCanvasLiTL.play()
$('#menuBtn').toggleClass('close')
$('.offCanvas').toggleClass('active')
$('body').toggleClass('offCanvas-active')
}
},
mounted() {
/////////////////////////////////////////////////////////// small header
$(window).scroll(function (e) {
if ($(window).scrollTop() > 50) {
$('.header,.offCanvas').addClass('header-small')
} else {
$('.header,.offCanvas').removeClass('header-small')
}
})
/////////////////////////////////// offCanvas menu links
$('.offCanvas ul li').click(() => {
this.offCanvas()
})
$('.header .lang-bar a').click(() => {
if ($('.offCanvas').hasClass('active')) this.offCanvas()
})
}
}
</script>
+37 -37
View File
@@ -1,42 +1,42 @@
<template>
<ul>
<admin-aside-item icon="fas fa-home" :link="{name: 'admin'}" text="صفحه اصلی"/>
<admin-aside-item icon="fas fa-presentation" :link="{name: 'admin-slider'}" text="اسلایدر"/>
<admin-aside-item icon="fa fa-gift" text="محصولات" :hasChild="true">
<admin-aside-item :link="{name: 'admin-products'}" text="لیست محصولات"/>
<admin-aside-item :link="{name: 'admin-products-category'}" text="دسته بندی محصولات"/>
</admin-aside-item>
<admin-aside-item icon="fa fa-newspaper" text="بلاگ" :hasChild="true">
<admin-aside-item :link="{name: 'admin-blog'}" text="لیست بلاگ"/>
<admin-aside-item :link="{name: 'admin-blog-category'}" text="دسته بندی بلاگ"/>
</admin-aside-item>
<admin-aside-item icon="fas fa-bags-shopping" :link="{name: 'admin-projects'}" text="پروژه ها"/>
<admin-aside-item icon="fas fa-history" :link="{name: 'admin-history'}" text="تاریخچه"/>
<admin-aside-item icon="fas fa-envelope" :badge="$store.state.admin.unread" :link="{name: 'admin-messages'}" text="پیام های ارتباط با ما"/>
<admin-aside-item icon="fas fa-file-pdf" :link="{name: 'admin-catalog'}" text="آپلود فایل کاتالوگ"/>
</ul>
<ul>
<admin-aside-item icon="fas fa-home" :link="{name: 'admin'}" text="صفحه اصلی"/>
<admin-aside-item icon="fas fa-presentation" :link="{name: 'admin-slider'}" text="اسلایدر"/>
<admin-aside-item icon="fa fa-gift" text="محصولات" :hasChild="true">
<admin-aside-item :link="{name: 'admin-products'}" text="لیست محصولات"/>
<admin-aside-item :link="{name: 'admin-products-category'}" text="دسته بندی محصولات"/>
</admin-aside-item>
<admin-aside-item icon="fa fa-newspaper" text="بلاگ" :hasChild="true">
<admin-aside-item :link="{name: 'admin-blog'}" text="لیست بلاگ"/>
<admin-aside-item :link="{name: 'admin-blog-category'}" text="دسته بندی بلاگ"/>
</admin-aside-item>
<admin-aside-item icon="fas fa-bags-shopping" :link="{name: 'admin-projects'}" text="پروژه ها"/>
<admin-aside-item icon="fas fa-history" :link="{name: 'admin-history'}" text="تاریخچه"/>
<admin-aside-item icon="fas fa-envelope" :badge="$store.state.admin.unread" :link="{name: 'admin-messages'}" text="پیام های ارتباط با ما"/>
<admin-aside-item icon="fas fa-file-pdf" :link="{name: 'admin-catalog'}" text="آپلود فایل کاتالوگ"/>
</ul>
</template>
<script>
export default {
mounted() {
if (this.$auth.loggedIn) {
this.$axios.get('/api/private/contact')
.then(response => {
let unread = response.data.filter(item => {
return !item.read
})
this.$store.commit('admin/unreadCount', unread.length)
})
}
}
}
export default {
mounted() {
if (this.$auth.loggedIn) {
this.$axios.get('/api/private/contact')
.then(response => {
let unread = response.data.filter(item => {
return !item.read
})
this.$store.commit('admin/unreadCount', unread.length)
})
}
}
}
</script>
+39 -37
View File
@@ -1,45 +1,47 @@
<template>
<div class="admin" v-if="$auth.loggedIn && $auth.user.scope.includes('admin')">
<!-- <div class="admin">-->
<div class="admin">
<admin-header/>
<div class="container-fluid">
<div class="row">
<aside class="admin--sidebar">
<admin-user v-if="$auth.loggedIn && $auth.user.scope.includes('admin')" :user="$auth.user.name"/>
<admin-aside/>
</aside>
<div class="admin--content">
<nuxt/>
</div>
</div>
</div>
</div>
</div>
<div class="admin" v-else>
<div class="admin--content" style="flex-basis: 100%!important;height: 100%!important;">
<div class="container">
<div class="row">
<nuxt/>
</div>
</div>
</div>
</div>
<div class="admin" v-if="$auth.loggedIn && $auth.user.scope.includes('admin')">
<!-- <div class="admin">-->
<div class="admin">
<admin-header/>
<div class="container-fluid">
<div class="row">
<aside class="admin--sidebar">
<div class="sidebar--content">
<admin-user v-if="$auth.loggedIn && $auth.user.scope.includes('admin')" :user="$auth.user.name"/>
<admin-aside/>
</div>
</aside>
<div class="admin--content">
<nuxt/>
</div>
</div>
</div>
</div>
</div>
<div class="admin" v-else>
<div class="admin--content" style="flex-basis: 100%!important;height: 100%!important;">
<div class="container">
<div class="row">
<nuxt/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
head() {
return {
htmlAttrs: {
lang: 'fa'
}
}
},
middleware: 'auth-admin'
}
export default {
head() {
return {
htmlAttrs: {
lang: 'fa'
}
}
},
middleware: 'auth-admin'
}
</script>
<style lang="scss">
@import "assets/admin/sass/admin";
@import "assets/admin/sass/admin";
</style>
+42 -35
View File
@@ -1,43 +1,50 @@
<template>
<div>
<SiteHeader/>
<nuxt/>
<SiteFooterHomePage v-if="this.$route.name === 'lang'"/>
<SiteFooterGlobal v-else/>
<off-canvas/>
<page-load/>
<pre-loader/>
</div>
<div>
<SiteHeader/>
<nuxt/>
<SiteFooterHomePage v-if="this.$route.name === 'lang'"/>
<SiteFooterGlobal v-else/>
<off-canvas/>
<page-load/>
<pre-loader/>
</div>
</template>
<script>
export default {
mounted() {
////////////////////////////////////////// global router guards
this.$router.beforeEach((to, from, next) => {
this.$gsap.timeline({
onComplete: () => {
next()
}
})
.to($('.page-load'), {autoAlpha: 1, duration: 0.3})
.fromTo($('.page-load svg'), {opacity: 0, scale: 1, y: 10}, {opacity: 1, y: 0, duration: 0.15})
.fromTo($('.page-load p'), {opacity: 0, scale: 1, y: 10}, {opacity: 1, y: 0, duration: 0.15})
})
export default {
mounted() {
////////////////////////////////////////// global router guards
this.$router.beforeEach((to, from, next) => {
this.$gsap.timeline({
onComplete: () => {
next()
}
})
.to($('.page-load'), {autoAlpha: 1, duration: 0.3})
.fromTo($('.page-load svg'), {opacity: 0, scale: 1, y: 10}, {opacity: 1, y: 0, duration: 0.15})
.fromTo($('.page-load p'), {opacity: 0, scale: 1, y: 10}, {opacity: 1, y: 0, duration: 0.15})
})
this.$router.afterEach((to, from) => {
this.$gsap.timeline({delay: 0.3})
.to($('.page-load p,.page-load svg'), {opacity: 0, scale: 0.5, duration: 0.15})
.to($('.page-load'), {autoAlpha: 0, duration: 0.5})
})
this.$router.afterEach((to, from) => {
this.$gsap.timeline({delay: 0.3})
.to($('.page-load p,.page-load svg'), {opacity: 0, scale: 0.5, duration: 0.15})
.to($('.page-load'), {autoAlpha: 0, duration: 0.5})
})
},
head() {
return {
htmlAttrs: {
lang: this.$route.params.lang
},
head() {
return {
htmlAttrs: {
lang: this.$route.params.lang
}
}
}
}
meta: [
{
hid: 'description',
name: 'description',
content: this.$store.state.global.meta_description[this.$route.params.lang]
}
],
}
}
}
</script>
+8 -8
View File
@@ -1,11 +1,11 @@
export default function ({route, redirect, error}) {
///////////// redirect to default local
if (route.path === '/') return redirect('/fa')
///////////// local check
const lang = ['fa', 'en']
const isLocal = lang.includes(route.params.lang)
const isAdmin = route.path.includes('/admin')
///////////// redirect to default local
if (route.path === '/') return redirect('/fa')
///////////// local check
const lang = ['fa', 'en']
const isLocal = lang.includes(route.params.lang)
const isAdmin = route.path.includes('/admin')
if (isLocal || isAdmin) return null
else error({statusCode: 404, message: 'Page Not Found'})
if (isLocal || isAdmin) return null
else error({statusCode: 404, message: 'Page Not Found'})
}
+84 -81
View File
@@ -1,92 +1,95 @@
const webpack = require("webpack")
export default {
// Global page headers (https://go.nuxtjs.dev/config-head)
head: {
title: 'Arak Rail',
meta: [
{charset: 'utf-8'},
{name: 'viewport', content: 'width=device-width, initial-scale=1'},
{hid: 'description', name: 'description', content: ''},
{name: 'theme-color', content: '#303030'},
],
link: [
{rel: 'icon', type: 'image/x-icon', href: '/favicon.png'}
]
},
// Global page headers (https://go.nuxtjs.dev/config-head)
head: {
title: 'اراک ریل',
meta: [
{charset: 'utf-8'},
{name: 'viewport', content: 'width=device-width, initial-scale=1'},
{name: 'theme-color', content: '#303030'},
],
link: [
{rel: 'icon', type: 'image/x-icon', href: '/favicon.png'}
]
},
// Global CSS (https://go.nuxtjs.dev/config-css)
loading: {
color: '#1B407C'
},
css: [
'slick-carousel/slick/slick.css',
'slick-carousel/slick/slick-theme.css',
'element-ui/lib/theme-chalk/index.css',
'~/assets/css/bootstrap-grid.css',
'~/assets/css/reset-css.css',
'~/assets/css/fontawesome/css/all.min.css',
'~/assets/sass/main.scss'
],
// Global CSS (https://go.nuxtjs.dev/config-css)
loading: {
color: '#1B407C'
},
css: [
'slick-carousel/slick/slick.css',
'slick-carousel/slick/slick-theme.css',
'element-ui/lib/theme-chalk/index.css',
'~/assets/css/bootstrap-grid.css',
'~/assets/css/reset-css.css',
'~/assets/css/fontawesome/css/all.min.css',
'~/assets/sass/main.scss'
],
// Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
plugins: [
'@/plugins/element-ui',
'@/plugins/ckEditor.client',
'@/plugins/datePicker.client',
'@/plugins/gsap.client'
],
// Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
plugins: [
'@/plugins/element-ui',
'@/plugins/ckEditor.client',
'@/plugins/datePicker.client',
'@/plugins/gsap.client'
],
// Auto import components (https://go.nuxtjs.dev/config-components)
components: true,
// Auto import components (https://go.nuxtjs.dev/config-components)
components: true,
// Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
buildModules: [],
// Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
buildModules: [],
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
'@nuxtjs/auth'
],
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
// https://go.nuxtjs.dev/axios
'@nuxtjs/axios',
'@nuxtjs/auth'
],
// Axios module configuration (https://go.nuxtjs.dev/config-axios)
axios: {
proxy: true
},
proxy: {
'/api': {target: 'http://127.0.0.1:7320'}
},
// Axios module configuration (https://go.nuxtjs.dev/config-axios)
axios: {
proxy: true
},
proxy: {
'/api': {target: 'http://127.0.0.1:7320'}
},
// Build Configuration (https://go.nuxtjs.dev/config-build)
build: {
transpile: [/^element-ui/],
vendor: ["jquery"],
plugins: [new webpack.ProvidePlugin({$: "jquery"})]
},
router: {
middleware: ['redirects'],
linkActiveClass: 'active'
},
server: {
host: '0.0.0.0',
port: 7320
},
serverMiddleware: ['~/api/index'],
auth: {
rewriteRedirects: true,
redirect: false,
strategies: {
local: {
endpoints: {
login: {url: '/api/auth/admin/login', method: 'post', propertyName: 'token'},
logout: {url: '/api/auth/admin/logout', method: 'post'},
user: {url: '/api/auth/admin/user', method: 'get', propertyName: 'user'}
},
tokenRequired: true,
tokenType: '',
globalToken: true,
autoFetchUser: true
}
// Build Configuration (https://go.nuxtjs.dev/config-build)
build: {
transpile: [/^element-ui/],
plugins: [new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})]
},
router: {
middleware: ['redirects'],
linkActiveClass: 'active'
},
server: {
host: '0.0.0.0',
port: 7320
},
serverMiddleware: ['~/api/index'],
auth: {
rewriteRedirects: true,
redirect: false,
strategies: {
local: {
endpoints: {
login: {url: '/api/auth/admin/login', method: 'post', propertyName: 'token'},
logout: {url: '/api/auth/admin/logout', method: 'post'},
user: {url: '/api/auth/admin/user', method: 'get', propertyName: 'user'}
},
tokenRequired: true,
tokenType: '',
globalToken: true,
autoFetchUser: true
}
}
}
}
}
+158 -158
View File
@@ -1,167 +1,167 @@
<template>
<div class="page about--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="parts p1">
<logo/>
<span>{{staticData.s1.t1}}</span>
<p>{{staticData.s1.t2}}</p>
</div>
<div class="parts p2 row">
<div class="col-12 col-lg-6 order-1 order-lg-0">
<p>{{staticData.s1.t3}}</p>
</div>
<div class="col-12 col-lg-6 order-0 order-lg-1 mb-5 mb-lg-0">
<div class="imgBox anim-fadeIn">
<div class="img">
<div class="shape"></div>
<img src="~/assets/img/about/about-s1-i1.jpg" alt="">
</div>
</div>
</div>
</div>
<div class="parts p3 row">
<div class="col-12 col-lg-6 mb-5 mb-lg-0">
<div class="imgBox imgBox-reverse anim-fadeIn">
<div class="img">
<div class="shape reverse"></div>
<img src="~/assets/img/about/about-s1-i2.jpg" alt="">
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<p>{{staticData.s1.t4}}</p>
</div>
</div>
<div class="parts p4 row">
<div class="col-12">
<p>{{staticData.s1.t5}}</p>
</div>
</div>
</div>
</div>
</section>
<section class="s2" v-if="history.length">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title title-shape-center">{{staticData.s2.t1}}</h2>
</div>
<div class="col-12">
<div class="timeline anim-fadeIn">
<template v-for="(item,index) in history">
<div class="circle" :key="item._id" :class="!index ? 'active' : null" :data-c-n="index" @click="activeHistory(item,index)">
<span>{{mDate(item.year)}}</span>
</div>
<div class="line" :key="item._id + 1" :data-l-n="index" v-if="index < history.length - 1"></div>
</template>
</div>
<div class="timeline-content anim-fadeIn">
<div class="row">
<div class="col-12 col-md-6 order-1 order-md-0">
<div class="txtBox">
<h5 ref="title">{{history[0].history_details[$route.params.lang].title}}</h5>
<p ref="caption">{{history[0].history_details[$route.params.lang].caption}}</p>
</div>
</div>
<div class="col-12 col-md-6 order-0 order-md-1 mb-3 mb-md-0">
<div class="imgBox" v-if="history.length">
<img ref="image" :src="history[0].image" :alt="history[0].history_details[$route.params.lang].title">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<h2 class="title title-shape">{{staticData.s3.t1}}</h2>
<p v-html="staticData.s3.t2"></p>
</div>
</section>
<section class="s4">
<div class="container">
<div v-for="(item , index) in staticData.s4" class="panel anim-fadeIn" :class="'p'+(index+1)">
<div class="row">
<div class="col-12 col-lg-5 img">
<img :src="require('~/assets/img/about/'+ item.img)" alt="">
</div>
<div class="col-12 col-lg-7 txt">
<p>{{item.title}}</p>
<a :href="item.link.url" class="btn btn-primary" target="_blank">{{item.link.txt}}</a>
</div>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
<div class="page about--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="parts p1">
<logo/>
<span>{{ staticData.s1.t1 }}</span>
<p>{{ staticData.s1.t2 }}</p>
</div>
<div class="parts p2 row">
<div class="col-12 col-lg-6 order-1 order-lg-0">
<p>{{ staticData.s1.t3 }}</p>
</div>
<div class="col-12 col-lg-6 order-0 order-lg-1 mb-5 mb-lg-0">
<div class="imgBox anim-fadeIn">
<div class="img">
<div class="shape"></div>
<img src="~/assets/img/about/about-s1-i1.jpg" alt="">
</div>
</div>
</div>
</div>
<div class="parts p3 row">
<div class="col-12 col-lg-6 mb-5 mb-lg-0">
<div class="imgBox imgBox-reverse anim-fadeIn">
<div class="img">
<div class="shape reverse"></div>
<img src="~/assets/img/about/about-s1-i2.jpg" alt="">
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<p>{{ staticData.s1.t4 }}</p>
</div>
</div>
<div class="parts p4 row">
<div class="col-12">
<p>{{ staticData.s1.t5 }}</p>
</div>
</div>
</div>
</div>
</section>
<section class="s2" v-if="history.length">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title title-shape-center">{{ staticData.s2.t1 }}</h2>
</div>
<div class="col-12">
<div class="timeline anim-fadeIn">
<template v-for="(item,index) in history">
<div class="circle" :key="item._id" :class="!index ? 'active' : null" :data-c-n="index" @click="activeHistory(item,index)">
<span>{{ mDate(item.year) }}</span>
</div>
<div class="line" :key="item._id + 1" :data-l-n="index" v-if="index < history.length - 1"></div>
</template>
</div>
<div class="timeline-content anim-fadeIn">
<div class="row">
<div class="col-12 col-md-6 order-1 order-md-0">
<div class="txtBox">
<h5 ref="title">{{ history[0].history_details[$route.params.lang].title }}</h5>
<p ref="caption">{{ history[0].history_details[$route.params.lang].caption }}</p>
</div>
</div>
<div class="col-12 col-md-6 order-0 order-md-1 mb-3 mb-md-0">
<div class="imgBox" v-if="history.length">
<img ref="image" :src="history[0].image" :alt="history[0].history_details[$route.params.lang].title">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<h2 class="title title-shape">{{ staticData.s3.t1 }}</h2>
<p v-html="staticData.s3.t2"></p>
</div>
</section>
<section class="s4">
<div class="container">
<div v-for="(item , index) in staticData.s4" class="panel anim-fadeIn" :class="'p'+(index+1)">
<div class="row">
<div class="col-12 col-lg-5 img">
<img :src="require('~/assets/img/about/'+ item.img)" alt="">
</div>
<div class="col-12 col-lg-7 txt">
<p>{{ item.title }}</p>
<a :href="`/standards_pdf/${item.link.url}`" download class="btn btn-primary" target="_blank">{{ item.link.txt }}</a>
</div>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
</template>
<script>
import moment from 'moment-jalaali'
import {fadeInAnimation} from '~/mixins/animations'
import moment from 'moment-jalaali'
import {fadeInAnimation} from '~/mixins/animations'
export default {
data() {
return {
history: null
}
},
computed: {
staticData() {
return this.$store.state.staticData.about[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
methods: {
activeHistory(item, index) {
for (let i = 0; i < this.history.length; i++) {
i > index ? $(`.circle[data-c-n="${i}"]`).removeClass('active') : null
i > index ? $(`.line[data-l-n="${i - 1}"]`).removeClass('active') : null
export default {
data() {
return {
history: null
}
},
computed: {
staticData() {
return this.$store.state.staticData.about[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
methods: {
activeHistory(item, index) {
for (let i = 0; i < this.history.length; i++) {
i > index ? $(`.circle[data-c-n="${i}"]`).removeClass('active') : null
i > index ? $(`.line[data-l-n="${i - 1}"]`).removeClass('active') : null
i < index ? $(`.circle[data-c-n="${i + 1}"]`).addClass('active') : null
i < index ? $(`.line[data-l-n="${i}"]`).addClass('active') : null
}
this.$gsap.timeline({
yoyo: true,
repeat: 1
}).to([this.$refs.image, this.$refs.title, this.$refs.caption],
{
opacity: 0,
duration: 0.1,
onComplete: () => {
this.$refs.image.src = item.image
this.$refs.title.textContent = item.history_details[this.$route.params.lang].title
this.$refs.caption.textContent = item.history_details[this.$route.params.lang].caption
}
})
},
mDate(date) {
if (this.$route.params.lang === 'en') return moment().jYear(date).year()
else return date
}
},
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios}) {
const history = await $axios.get(`/api/public/history`)
return {
history: history.data
}
i < index ? $(`.circle[data-c-n="${i + 1}"]`).addClass('active') : null
i < index ? $(`.line[data-l-n="${i}"]`).addClass('active') : null
}
}
this.$gsap.timeline({
yoyo: true,
repeat: 1
}).to([this.$refs.image, this.$refs.title, this.$refs.caption],
{
opacity: 0,
duration: 0.1,
onComplete: () => {
this.$refs.image.src = item.image
this.$refs.title.textContent = item.history_details[this.$route.params.lang].title
this.$refs.caption.textContent = item.history_details[this.$route.params.lang].caption
}
})
},
mDate(date) {
if (this.$route.params.lang === 'en') return moment().jYear(date).year()
else return date
}
},
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios}) {
const history = await $axios.get(`/api/public/history`)
return {
history: history.data
}
}
}
</script>
+88 -88
View File
@@ -1,96 +1,96 @@
<template>
<div class="page blog-details--page">
<Hero :title="categoryName(post.category)"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="date-category">
<div class="page blog-details--page latin-digits">
<Hero :title="categoryName(post.category)"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="date-category">
<span class="category">
<span>{{staticData.t1}}</span>
<span>{{categoryName(post.category)}}</span>
<span>{{ staticData.t1 }}</span>
<span>{{ categoryName(post.category) }}</span>
</span>
<span class="date">{{jDate(post.created_at)}}</span>
</div>
<div class="content" v-html="post.post_details[$route.params.lang].description"></div>
<div class="share">
<p>{{staticData.t2}}</p>
<ul>
<li>
<a target="_blank" title="Twitter" :href="'https://twitter.com/intent/tweet?url=' + domain + $route.fullPath">
<i class="fab fa-twitter"></i>
</a>
</li>
<li>
<a target="_blank" title="WhatsApp" :href="'whatsapp://send?text=' + domain + $route.fullPath">
<i class="fab fa-whatsapp"></i>
</a>
</li>
<li>
<a target="_blank" title="Linked In" :href="'https://www.linkedin.com/shareArticle?mini=true&url=' + domain + $route.fullPath">
<i class="fab fa-linkedin-in"></i>
</a>
</li>
<li>
<a target="_blank" title="Facebook" :href="'https://www.facebook.com/sharer.php?u=' + domain + $route.fullPath">
<i class="fab fa-facebook-f"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{staticData.t3}}</h2>
<nuxt-link :to="{name: 'lang-blog',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.t4}}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
<span class="date">{{ jDate(post.created_at) }}</span>
</div>
<div class="ck-content" v-html="post.post_details[$route.params.lang].description"></div>
<div class="share">
<p>{{ staticData.t2 }}</p>
<ul>
<li>
<a target="_blank" title="Twitter" :href="'https://twitter.com/intent/tweet?url=' + domain + $route.fullPath">
<i class="fab fa-twitter"></i>
</a>
</li>
<li>
<a target="_blank" title="WhatsApp" :href="'whatsapp://send?text=' + domain + $route.fullPath">
<i class="fab fa-whatsapp"></i>
</a>
</li>
<li>
<a target="_blank" title="Linked In" :href="'https://www.linkedin.com/shareArticle?mini=true&url=' + domain + $route.fullPath">
<i class="fab fa-linkedin-in"></i>
</a>
</li>
<li>
<a target="_blank" title="Facebook" :href="'https://www.facebook.com/sharer.php?u=' + domain + $route.fullPath">
<i class="fab fa-facebook-f"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{ staticData.t3 }}</h2>
<nuxt-link :to="{name: 'lang-blog',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t4 }}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
</template>
<script>
import moment from "moment-jalaali"
import moment from "moment-jalaali"
export default {
data() {
return {
post: null,
blogCategories: null,
domain: 'https://www.arakrail.com'
}
},
computed: {
staticData() {
return this.$store.state.staticData.blog_details[this.$route.params.lang]
}
},
methods: {
categoryName(id) {
return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name
},
jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD')
else return date.split(' ')[0]
},
},
head() {
return {
title: this.post.post_details[this.$route.params.lang].title
}
},
async asyncData({$axios, params}) {
const post = await $axios.get(`/api/public/blog/${params.post}`)
const blogCategories = await $axios.get(`/api/public/blogCategories`)
return {
post: post.data,
blogCategories: blogCategories.data
}
}
}
export default {
data() {
return {
post: null,
blogCategories: null,
domain: 'https://www.arakrail.com'
}
},
computed: {
staticData() {
return this.$store.state.staticData.blog_details[this.$route.params.lang]
}
},
methods: {
categoryName(id) {
return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name
},
jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD')
else return date.split(' ')[0]
},
},
head() {
return {
title: this.post.post_details[this.$route.params.lang].title
}
},
async asyncData({$axios, params}) {
const post = await $axios.get(`/api/public/blog/${params.post}`)
const blogCategories = await $axios.get(`/api/public/blogCategories`)
return {
post: post.data,
blogCategories: blogCategories.data
}
}
}
</script>
+122 -122
View File
@@ -1,131 +1,131 @@
<template>
<div class="page blog--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{staticData.t1}}</h2>
<p>{{staticData.t2}}</p>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<div class="filters anim-fadeIn">
<h2 class="title">{{staticData.t3}}</h2>
<ul>
<li @click="filtering(false)">
<p class="active">{{staticData.t7}}</p>
</li>
<li v-for="item in blogCategories" :key="item._id" @click="filtering(item._id)">
<p>{{item.blogCategory_details[$route.params.lang].name}}</p>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<div class="row posts-container" v-if="filtered_posts.length">
<div class="col-12 col-sm-6 col-lg-12 clearfix post anim-fadeIn" v-for="item in filtered_posts" :key="item._id">
<div class="panel">
<div class="imgBox imgBox-reverse">
<div class="img">
<img :src="item.thumb" :alt="item.post_details[$route.params.lang].title">
</div>
</div>
<div class="txtBox">
<div class="date-category">
<div class="page blog--page latin-digits">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{ staticData.t1 }}</h2>
<p>{{ staticData.t2 }}</p>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<div class="filters anim-fadeIn">
<h2 class="title">{{ staticData.t3 }}</h2>
<ul>
<li @click="filtering(false)">
<p class="active">{{ staticData.t7 }}</p>
</li>
<li v-for="item in blogCategories" :key="item._id" @click="filtering(item._id)">
<p>{{ item.blogCategory_details[$route.params.lang].name }}</p>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<div class="row posts-container" v-if="filtered_posts.length">
<div class="col-12 col-md-6 col-lg-12 clearfix post anim-fadeIn" v-for="item in filtered_posts" :key="item._id">
<div class="panel">
<div class="imgBox imgBox-reverse">
<div class="img">
<img :src="item.thumb" :alt="item.post_details[$route.params.lang].title">
</div>
</div>
<div class="txtBox">
<div class="date-category">
<span class="category">
<span>{{staticData.t4}}</span>
<span>{{categoryName(item.category)}}</span>
<span>{{ staticData.t4 }}</span>
<span>{{ categoryName(item.category) }}</span>
</span>
<span class="date">{{jDate(item.created_at)}}</span>
</div>
<h4>{{item.post_details[$route.params.lang].title}}</h4>
<p>{{item.post_details[$route.params.lang].short_description}}</p>
<nuxt-link :to="{name: 'lang-blog-post',params: {lang: $route.params.lang,post: item._id}}" class="btn btn-primary">{{staticData.t5}}</nuxt-link>
</div>
</div>
</div>
</div>
<div class="row" v-else>
<div class="col-12">
<p class="no-post posts-container anim-fadeIn">{{staticData.t6}}</p>
</div>
</div>
</div>
</section>
</div>
<span class="date">{{ jDate(item.created_at) }}</span>
</div>
<h4>{{ item.post_details[$route.params.lang].title }}</h4>
<p>{{ item.post_details[$route.params.lang].short_description }}</p>
<nuxt-link :to="{name: 'lang-blog-post',params: {lang: $route.params.lang,post: item._id}}" class="btn btn-primary">{{ staticData.t5 }}</nuxt-link>
</div>
</div>
</div>
</div>
<div class="row" v-else>
<div class="col-12">
<p class="no-post posts-container anim-fadeIn">{{ staticData.t6 }}</p>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
import moment from 'moment-jalaali'
import {fadeInAnimation} from "~/mixins/animations"
import moment from 'moment-jalaali'
import {fadeInAnimation} from "~/mixins/animations"
export default {
data() {
return {
posts: null,
blogCategories: null,
filter: false
}
},
computed: {
staticData() {
return this.$store.state.staticData.blog[this.$route.params.lang]
},
filtered_posts() {
if (!this.filter) return this.posts
else return this.posts.filter(item => item.category === this.filter)
}
},
methods: {
categoryName(id) {
return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name
},
jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD')
else return date.split(' ')[0]
},
filtering(key) {
$('.blog--page .filters p').removeClass('active')
$(event.target).addClass('active')
export default {
data() {
return {
posts: null,
blogCategories: null,
filter: false
}
},
computed: {
staticData() {
return this.$store.state.staticData.blog[this.$route.params.lang]
},
filtered_posts() {
if (!this.filter) return this.posts
else return this.posts.filter(item => item.category === this.filter)
}
},
methods: {
categoryName(id) {
return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name
},
jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD')
else return date.split(' ')[0]
},
filtering(key) {
$('.blog--page .filters p').removeClass('active')
$(event.target).addClass('active')
this.$gsap.timeline({
yoyo: true,
repeat: 1
})
.to($('.blog--page .posts-container'),
{
opacity: 0,
duration: 0.3,
onComplete: () => {
this.filter = key
}
})
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios, store}) {
let posts = await $axios.get(`/api/public/blog`)
const blogCategories = await $axios.get(`/api/public/blogCategories`)
return {
posts: posts.data,
blogCategories: blogCategories.data
}
}
}
this.$gsap.timeline({
yoyo: true,
repeat: 1
})
.to($('.blog--page .posts-container'),
{
opacity: 0,
duration: 0.3,
onComplete: () => {
this.filter = key
}
})
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios, store}) {
let posts = await $axios.get(`/api/public/blog`)
const blogCategories = await $axios.get(`/api/public/blogCategories`)
return {
posts: posts.data,
blogCategories: blogCategories.data
}
}
}
</script>
+456 -211
View File
@@ -1,224 +1,469 @@
<template>
<div class="page calculation--page">
<Hero title="نرم افزار محاسبه"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">وزن گریتینگ</h2>
<p>بدلیل این که وزن گریتینگ ها به واسطه مواردی همچون مشخصات فنی یا همان دیتیل ساخت از جمله نوع گریتینگ،جنس تسمه و اندازه چشمه ها متغیر است،بدین منظور جهت راحتی و سهولت در انجام کار شما مشتری گرامی، شرکت اراک ریل نرم افزار محاسبه وزن و میزان بار قابل تحمل را برای گریتینگ طراحی و در این صفحه قرار داده است.که با داشتن مشخصات فنی گریتینگ مورد نظر خود میتوانید وزن گریتینگ خود را همراه با گالوانیزه و یا بدون گالوانیزه محاسبه کنید.</p>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="app m-auto" :class="app.method === 'a' ? 'col-12 col-lg-6' : 'col-12'">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="appTitle">
<h2 class="title">ظرفیت بارگیری گریتینگ خود را محاسبه کنید</h2>
</div>
<div class="appMethod">
<span>روش محاسبه</span>
<el-radio-group v-model="app.method" style="direction: ltr">
<el-radio-button label="b">نفر یا وسیله نقلیه</el-radio-button>
<el-radio-button label="a">وارد کردن بار</el-radio-button>
</el-radio-group>
</div>
</div>
<div class="col-12 col-lg-6 mb-5 mb-lg-0" v-if="app.method === 'b'">
<div class="appLayout">
<h2 class="layoutTitle">انتخاب کلاس لودینگ</h2>
<div class="class">
<h4>عابر پیاده:</h4>
<el-radio v-model="app.class" :label="1">کلاس 1</el-radio>
</div>
<div class="class">
<h4>وسایل نقلیه:</h4>
<el-radio v-model="app.class" :label="2">کلاس 2</el-radio>
<el-radio v-model="app.class" :label="3">کلاس 3</el-radio>
<el-radio v-model="app.class" :label="4">کلاس 4</el-radio>
</div>
<div class="class">
<h4>لیفتراک:</h4>
<el-radio v-model="app.class" :label="5">FL1</el-radio>
<el-radio v-model="app.class" :label="6">FL2</el-radio>
<el-radio v-model="app.class" :label="7">FL3</el-radio>
<el-radio v-model="app.class" :label="8">FL4</el-radio>
<el-radio v-model="app.class" :label="9">FL5</el-radio>
<el-radio v-model="app.class" :label="10">FL6</el-radio>
</div>
</div>
</div>
<div :class="app.method === 'a' ? 'col-12' : 'col-12 col-lg-6'">
<div class="appLayout">
<h2 class="layoutTitle">اطلاعات ورودی</h2>
<el-form key="form-a">
<el-form-item label="نوع گریتینگ">
<el-radio-group v-model="app.type">
<el-radio label="elec">الکتروفورج</el-radio>
<el-radio label="press">پرسی</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="بار متمرکز (kn)">
<el-input v-model="app.pointLoad" placeholder="وارد کنید"></el-input>
<!-- <span>kn</span>-->
</el-form-item>
<el-form-item label="بار گسترده (kn/m2)">
<el-input v-model="app.distributedLoad" placeholder="وارد کنید"></el-input>
<!-- <span>kn/m2</span>-->
</el-form-item>
<el-form-item label="گام تسمه های باربر (mm)">
<el-select v-model="app.bearingBarPitch" key="bearingBarPitch_elec" v-if="app.type === 'elec'" placeholder="انتخاب کنید">
<el-option
v-for="item in bearingBarPitch_elec"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="app.bearingBarPitch" key="bearingBarPitch_press" v-if="app.type === 'press'" placeholder="انتخاب کنید">
<el-option
v-for="item in bearingBarPitch_press"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<!-- <span>mm</span>-->
</el-form-item>
<el-form-item label="گام تسمه های رابط (mm)">
<el-select v-model="app.crossBarPitCh" key="bearingBarPitch_elec" v-if="app.type === 'elec'" placeholder="انتخاب کنید">
<el-option
v-for="item in crossBarPitCh_elec"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="app.crossBarPitCh" key="bearingBarPitch_press" v-if="app.type === 'press'" placeholder="انتخاب کنید">
<el-option
v-for="item in crossBarPitCh_press"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<!-- <span>mm</span>-->
</el-form-item>
<el-form-item label="دهنه باربر (mm)">
<el-input v-model="app.clearSpan" placeholder="وارد کنید"></el-input>
<!-- <span>mm</span>-->
</el-form-item>
<el-form-item label="ضخامت تسمه های باربر (mm)">
<el-input v-model="app.bearingBarThickness" placeholder="وارد کنید"></el-input>
<!-- <span>mm</span>-->
</el-form-item>
<el-form-item label="ارتفاع تسمه های باربر (mm)">
<el-select v-model="app.bearingBarHeight" key="bearingBarHeight" placeholder="انتخاب کنید">
<el-option
v-for="item in bearingBarHeight"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<!-- <span>mm</span>-->
</el-form-item>
<div class="calculateBtn">
<!-- <el-button>محاسبه</el-button>-->
<button class="btn btn-reverse-fill">محاسبه</button>
</div>
</el-form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<div class="page calculation--page latin-digits">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{ staticData.app.t1 }}</h2>
<p>{{ staticData.app.t2 }}</p>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="app m-auto" :class="app.method === 'custom' ? 'col-12 col-lg-9 col-xl-8 col-xxl-6' : 'col-12'">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="appTitle">
<h2 class="title">{{ staticData.app.t3 }}</h2>
</div>
<div class="appMethod">
<span class="txt">{{ staticData.app.t4 }}</span>
<el-radio-group v-model="app.method" style="direction: ltr">
<template v-if="$route.params.lang === 'fa'">
<el-radio-button label="classified">{{ staticData.app.t5 }}</el-radio-button>
<el-radio-button label="custom">{{ staticData.app.t6 }}</el-radio-button>
</template>
<template v-else>
<el-radio-button label="custom">{{ staticData.app.t6 }}</el-radio-button>
<el-radio-button label="classified">{{ staticData.app.t5 }}</el-radio-button>
</template>
</el-radio-group>
</div>
</div>
<div class="col-12 col-lg-6 mb-5 mb-lg-0" v-if="app.method === 'classified'">
<div class="appLayout">
<h2 class="layoutTitle">{{ staticData.app.t7 }}</h2>
<div class="class">
<h4>{{ staticData.app.t8 }}</h4>
<el-radio v-model="app.vehicleClass" label="class1">{{ staticData.app.t9 }}</el-radio>
</div>
<div class="class">
<h4>{{ staticData.app.t10 }}</h4>
<el-radio v-model="app.vehicleClass" label="class2">{{ staticData.app.t11 }}</el-radio>
<el-radio v-model="app.vehicleClass" label="class3">{{ staticData.app.t12 }}</el-radio>
<el-radio v-model="app.vehicleClass" label="class4">{{ staticData.app.t13 }}</el-radio>
</div>
<div class="class">
<h4>{{ staticData.app.t14 }}</h4>
<el-radio v-model="app.vehicleClass" label="FL1">FL1</el-radio>
<el-radio v-model="app.vehicleClass" label="FL2">FL2</el-radio>
<el-radio v-model="app.vehicleClass" label="FL3">FL3</el-radio>
<el-radio v-model="app.vehicleClass" label="FL4">FL4</el-radio>
<el-radio v-model="app.vehicleClass" label="FL5">FL5</el-radio>
<el-radio v-model="app.vehicleClass" label="FL6">FL6</el-radio>
</div>
</div>
</div>
<div :class="app.method === 'custom' ? 'col-12' : 'col-12 col-lg-6'">
<div class="appLayout">
<h2 class="layoutTitle">{{ staticData.app.t15 }}</h2>
<el-form key="form-a">
<el-form-item :label="staticData.app.t16">
<el-radio-group v-model="app.gratingType">
<el-radio label="forge">{{ staticData.app.t17 }}</el-radio>
<el-radio label="pressured">{{ staticData.app.t18 }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="staticData.app.t19" v-if="app.method === 'custom'">
<el-radio-group v-model="app.loadType">
<el-radio label="pointedLoad">{{ staticData.app.t20 }}</el-radio>
<el-radio label="distributedLoad">{{ staticData.app.t21 }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :class="validation.pointedLoadValue ? 'is-error' : null" :label="staticData.app.t22" v-if="app.method === 'custom' && app.loadType === 'pointedLoad'">
<el-input v-model="app.pointedLoadValue" :placeholder="staticData.app.enter"></el-input>
<p class="err" v-if="validation.pointedLoadValue">{{ validation.pointedLoadValue.msg }}</p>
</el-form-item>
<el-form-item :class="validation.distributedLoadValue ? 'is-error' : null" :label="staticData.app.t23" v-if="app.method === 'custom' && app.loadType === 'distributedLoad'">
<el-input v-model="app.distributedLoadValue" :placeholder="staticData.app.enter"></el-input>
<p class="err" v-if="validation.distributedLoadValue">{{ validation.distributedLoadValue.msg }}</p>
</el-form-item>
<el-form-item :class="validation.bearingBarPitch ? 'is-error' : null" :label="staticData.app.t24">
<el-select v-model="app.bearingBarPitch" key="bearingBarPitch_forge" v-if="app.gratingType === 'forge'"
:placeholder="staticData.app.select">
<el-option
v-for="item in calculationValues.bearingBarPitch_forge"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="app.bearingBarPitch" key="bearingBarPitch_pressured" v-if="app.gratingType === 'pressured'" :placeholder="staticData.app.select">
<el-option
v-for="item in calculationValues.bearingBarPitch_pressured"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<p class="err" v-if="validation.bearingBarPitch">{{ validation.bearingBarPitch.msg }}</p>
</el-form-item>
<el-form-item :class="validation.crossBarPitch ? 'is-error' : null" :label="staticData.app.t25">
<el-select v-model="app.crossBarPitch" key="crossBarPitch_forge" v-if="app.gratingType === 'forge'" :placeholder="staticData.app.select">
<el-option
v-for="item in calculationValues.crossBarPitch_forge"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<el-select v-model="app.crossBarPitch" key="crossBarPitch_pressured" v-if="app.gratingType === 'pressured'" :placeholder="staticData.app.select">
<el-option
v-for="item in calculationValues.crossBarPitch_pressured"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<p class="err" v-if="validation.crossBarPitch">{{ validation.crossBarPitch.msg }}</p>
</el-form-item>
<el-form-item :class="validation.clearSpan ? 'is-error' : null" :label="staticData.app.t26">
<el-input v-model="app.clearSpan" :placeholder="staticData.app.enter"></el-input>
<p class="err" v-if="validation.clearSpan">{{ validation.clearSpan.msg }}</p>
</el-form-item>
<el-form-item :class="validation.bearingBarThickness ? 'is-error' : null" :label="staticData.app.t27">
<el-input v-model="app.bearingBarThickness" :placeholder="staticData.app.enter"></el-input>
<p class="err" v-if="validation.bearingBarThickness">{{ validation.bearingBarThickness.msg }}</p>
</el-form-item>
<el-form-item :class="validation.bearingBarHeight ? 'is-error' : null" :label="staticData.app.t28">
<el-select v-model="app.bearingBarHeight"
key="bearingBarHeight"
:placeholder="relativeValues || app.loadType === 'distributedLoad' ? staticData.app.select : staticData.app.t29">
<el-option
v-for="item in app.loadType === 'distributedLoad' ? calculationValues.bearingBarHeight : relativeValues"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<p class="err" v-if="validation.bearingBarHeight">{{ validation.bearingBarHeight.msg }}</p>
</el-form-item>
<div class="calculateBtn">
<button class="btn btn-reverse-fill" @click.prevent="calculate">{{ staticData.app.calculate }}</button>
</div>
</el-form>
</div>
</div>
<div class="col-12 mt-5">
<div class="appResult" v-if="waiting || appResult || validation">
<p class="waiting" v-if="waiting">{{ staticData.app.waiting }}</p>
<p class="err" v-if="!appResult">{{ staticData.app.validationErr }}</p>
<p v-if="appResult" :class="appResult.sigmaStatus ? 'success' : 'failure'">{{ appResult.sigma }}</p>
<p v-if="appResult" :class="appResult.deflectionStatus ? 'success' : 'failure'">{{ appResult.deflection }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<div class="row">
<div class="col-12">
<div class="tableBox vehicles">
<table>
<thead>
<tr>
<th colspan="4" class="center">{{ staticData.table1.title }}</th>
<th class="middle">{{ staticData.table1.load }}</th>
<th>{{ staticData.table1.imprint }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ staticData.table1.class1.t1 }}</td>
<td>{{ staticData.table1.class1.t2 }}</td>
<td>{{ staticData.table1.class1.t3 }}</td>
<td>{{ staticData.table1.danSqm }}</td>
<td>600</td>
<td>1000 x 1000</td>
</tr>
<tr class="odd">
<td>{{ staticData.table1.class2.t1 }}</td>
<td>{{ staticData.table1.class2.t2 }}</td>
<td>{{ staticData.table1.class2.t3 }}</td>
<td>{{ staticData.table1.danImprint }}</td>
<td>1.000</td>
<td>200 x 200</td>
</tr>
<tr>
<td>{{ staticData.table1.class3.t1 }}</td>
<td>{{ staticData.table1.class3.t2 }}</td>
<td>{{ staticData.table1.class3.t3 }}</td>
<td>{{ staticData.table1.danImprint }}</td>
<td>3.000</td>
<td>200 x 400</td>
</tr>
<tr class="odd">
<td>{{ staticData.table1.class4.t1 }}</td>
<td>{{ staticData.table1.class4.t2 }}</td>
<td>{{ staticData.table1.class4.t3 }}</td>
<td>{{ staticData.table1.danImprint }}</td>
<td>9.000</td>
<td>250 x 600</td>
</tr>
</tbody>
</table>
</div>
<p class="notice">{{ staticData.scrollToSee }}</p>
<div class="tableBox forklifts">
<table>
<thead>
<tr>
<th colspan="6" class="center">{{ staticData.table2.title }}</th>
<th class="middle">{{ staticData.table2.load }}</th>
<th>{{ staticData.table2.imprint }}</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>{{ staticData.table2.t1 }}</td>
<td>{{ staticData.table2.t2 }}</td>
<td>{{ staticData.table2.t3 }}</td>
<td>{{ staticData.table2.t4 }}</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>{{ staticData.table2.fl1.t1 }}</td>
<td>{{ staticData.table2.fl1.t2 }}</td>
<td>21</td>
<td>10</td>
<td>31</td>
<td>{{ staticData.table2.danImprint }}</td>
<td>2600</td>
<td>130 x 130</td>
</tr>
<tr>
<td>{{ staticData.table2.fl2.t1 }}</td>
<td>{{ staticData.table2.fl2.t2 }}</td>
<td>31</td>
<td>15</td>
<td>46</td>
<td>{{ staticData.table2.danImprint }}</td>
<td>4000</td>
<td>175 x 150</td>
</tr>
<tr class="odd">
<td>{{ staticData.table2.fl3.t1 }}</td>
<td>{{ staticData.table2.fl3.t2 }}</td>
<td>44</td>
<td>25</td>
<td>69</td>
<td>{{ staticData.table2.danImprint }}</td>
<td>6300</td>
<td>200 x 200</td>
</tr>
<tr>
<td>{{ staticData.table2.fl4.t1 }}</td>
<td>{{ staticData.table2.fl4.t2 }}</td>
<td>60</td>
<td>40</td>
<td>100</td>
<td>{{ staticData.table2.danImprint }}</td>
<td>9000</td>
<td>300 x 200</td>
</tr>
<tr class="odd">
<td>{{ staticData.table2.fl5.t1 }}</td>
<td>{{ staticData.table2.fl5.t2 }}</td>
<td>90</td>
<td>60</td>
<td>150</td>
<td>{{ staticData.table2.danImprint }}</td>
<td>14000</td>
<td>375 x 200</td>
</tr>
<tr>
<td>{{ staticData.table2.fl6.t1 }}</td>
<td>{{ staticData.table2.fl6.t2 }}</td>
<td>110</td>
<td>80</td>
<td>190</td>
<td>{{ staticData.table2.danImprint }}</td>
<td>17000</td>
<td>450 x 200</td>
</tr>
</tbody>
</table>
</div>
<p class="notice">{{ staticData.scrollToSee }}</p>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
import moment from 'moment-jalaali'
import {fadeInAnimation} from '~/mixins/animations'
import {fadeInAnimation} from '~/mixins/animations'
export default {
data() {
return {
history: null,
app: {
method: 'a',
type: 'elec',
class: '',
pointLoad: '',
distributedLoad: '',
bearingBarPitch: '',
crossBarPitCh: '',
clearSpan: '',
bearingBarThickness: '',
bearingBarHeight: '',
locale: this.$route.params.lang
},
bearingBarPitch_elec: [30, 35, 41, 50],
bearingBarPitch_press: [11, 22, 33, 44, 50, 55],
crossBarPitCh_elec: [50, 76, 100],
crossBarPitCh_press: [11, 22, 33, 44, 50, 55, 66, 77, 88, 100],
bearingBarHeight: [20, 25, 30, 35, 40, 45, 50, 55, 60]
}
export default {
data() {
return {
app: {
method: 'custom',
gratingType: 'forge',
loadType: 'pointedLoad',
vehicleClass: 'class1',
pointedLoadValue: '',
distributedLoadValue: '',
bearingBarPitch: '',
crossBarPitch: '',
clearSpan: '',
bearingBarThickness: '',
bearingBarHeight: '',
locale: this.$route.params.lang
},
computed: {
staticData() {
return this.$store.state.staticData.calculation[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
methods: {},
head() {
return {
htmlAttrs: {
title: this.staticData.hero
}
}
calculationValues: null,
relativeValues: null,
validation: {},
waiting: false,
appResult: null
}
},
computed: {
staticData() {
return this.$store.state.staticData.calculation[this.$route.params.lang]
},
gratingTypeTrigger() {
return this.app.gratingType
},
crossBarPitchTrigger() {
return this.app.crossBarPitch
},
loadTypeTrigger() {
return this.app.loadType
},
vehicleClassTrigger() {
return this.app.vehicleClass
},
methodTrigger() {
return this.app.method
}
},
watch: {
loadTypeTrigger(newVal, oldVal) {
this.app.bearingBarHeight = ''
},
gratingTypeTrigger(newVal, oldVal) {
this.app.bearingBarPitch = ''
this.app.crossBarPitch = ''
},
crossBarPitchTrigger(newVal, oldVal) {
if (this.app.loadType === 'pointedLoad') {
this.app.bearingBarHeight = ''
const data = {
gratingType: this.app.gratingType,
crossBarPitch: this.app.crossBarPitch
}
this.$axios.post('/api/public/calculation/relativeValues', data)
.then(res => {
this.relativeValues = res.data
})
.catch(err => {
this.relativeValues = null
})
}
}
},
vehicleClassTrigger(newVal, oldVal) {
this.app.crossBarPitch = ''
if (newVal === 'class1') this.app.loadType = 'distributedLoad'
else this.app.loadType = 'pointedLoad'
},
methodTrigger(newVal, oldVal) {
if (newVal === 'classified') {
this.app.vehicleClass = 'class1'
this.app.loadType = 'distributedLoad'
} else {
this.app.vehicleClass = ''
this.app.loadType = 'pointedLoad'
}
},
waiting() {
setTimeout(() => {
this.$gsap.to($('.app .appResult'), {opacity: 1, minHeight: 145, height: 'auto', paddingTop: 30, paddingBottom: 30, duration: 0.5})
}, 100)
}
},
mixins: [fadeInAnimation],
methods: {
calculate() {
this.validation = {}
this.waiting = true
this.appResult = null
this.$axios.post('/api/public/calculate', this.app)
.then(res => {
this.waiting = false
this.appResult = res.data
})
.catch(err => {
this.waiting = false
if (err.response.status === 422) this.validation = err.response.data.validation
})
}
},
head() {
return {
htmlAttrs: {
title: this.staticData.hero
}
}
},
async asyncData({$axios}) {
const calculationValues = await $axios.get('/api/public/calculation/values')
return {
calculationValues: calculationValues.data
}
}
}
</script>
<style lang="scss">
.el-popper .popper__arrow {
border-width: 0;
filter: none;
left: 35px;
&:lang(fa) {
left: auto;
right: 35px;
}
}
.el-popper .popper__arrow {
border-width: 0;
filter: none;
left: 35px;
&:lang(fa) {
left: auto;
right: 35px;
}
}
</style>
+201 -200
View File
@@ -1,209 +1,210 @@
<template>
<div class="page contact--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="row">
<div class="col-12 p1">
<h2 class="title">{{staticData.t1}}</h2>
<p>{{staticData.t2}}</p>
</div>
<div class="col-12 p2">
<ul>
<li>
<i class="fas fa-map-marker-alt"></i>
<span>{{staticData.t3}}</span>
</li>
<li>
<i class="fas fa-phone"></i>
<a href="tel: +988634132704">Tell: +98 86 3 413 2704 - 7</a>
-
<a href="tel: +988634132703">Fax: +98 86 3 413 27 03</a>
</li>
<li>
<i class="fas fa-envelope"></i>
<a href="mailto: info@arakrail.com">info@arakrail.com</a>
</li>
</ul>
</div>
<div class="col-12 p3">
<hr>
<b>{{staticData.t4}}</b>
<p>{{staticData.t5}}</p>
<ul>
<li>
<a href="" target="_blank">
<i class="fab fa-facebook-f"></i>
</a>
</li>
<li>
<a href="" target="_blank">
<i class="fab fa-twitter"></i>
</a>
</li>
<li>
<a href="" target="_blank">
<i class="fab fa-telegram-plane"></i>
</a>
</li>
</ul>
</div>
<div class="col-12 p4">
<div class="mapouter">
<div class="gmap_canvas">
<iframe id="gmap_canvas"
src="https://maps.google.com/maps?q=%D8%A7%D8%B1%D8%A7%DA%A9%20%D8%B1%DB%8C%D9%84%20%D8%8C%D8%A7%D8%B3%D8%AA%D8%A7%D9%86%20%D9%85%D8%B1%DA%A9%D8%B2%DB%8C%D8%8C%20%D8%A7%D8%B1%D8%A7%DA%A9%D8%8C%20%D8%B4%D9%87%D8%B1%DA%A9%20%D9%82%D8%B7%D8%A8%20%D8%B5%D9%86%D8%B9%D8%AA%DB%8C%D8%8C%20%D8%AE%DB%8C%D8%A7%D8%A8%D8%A7%D9%86%20%D8%AA%D9%84%D8%A7%D8%B4%D8%8C%20%D9%87%D9%85%D8%AA&t=&z=13&ie=UTF8&iwloc=&output=embed"
frameborder="0" scrolling="no" marginheight="0" marginwidth="0">
</iframe>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="panel">
<div class="row">
<div class="col-12">
<h2>{{staticData.t6}}</h2>
<form class="form" @submit.prevent="upload">
<div class="row">
<div class="col-12">
<div class="formRow center-align" :class="validation.reason ? 'err' : null">
<select name="reason" v-model="formData.reason">
<option disabled selected :value="false">{{staticData.t7}}</option>
<option v-for="item in reasons" :key="item._id" :value="item.reason_details.fa.reason">{{item.reason_details[$route.params.lang].reason}}</option>
</select>
<p v-if="validation.reason">{{validation.reason.msg}}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.first_name ? 'err' : null">
<input type="text" :placeholder="staticData.t8" name="first_name" v-model="formData.first_name">
<p v-if="validation.first_name">{{validation.first_name.msg}}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.last_name ? 'err' : null">
<input type="text" :placeholder="staticData.t9" name="last_name" v-model="formData.last_name">
<p v-if="validation.last_name">{{validation.last_name.msg}}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.phone_number ? 'err' : null">
<input type="text" :placeholder="staticData.t10" name="phone_number" v-model="formData.phone_number">
<p v-if="validation.phone_number">{{validation.phone_number.msg}}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.email ? 'err' : null">
<input type="text" :placeholder="staticData.t11" name="email" v-model="formData.email">
<p v-if="validation.email">{{validation.email.msg}}</p>
</div>
</div>
<div class="col-12">
<div class="formRow" :class="validation.message ? 'err' : null">
<textarea :placeholder="staticData.t12" name="message" v-model="formData.message"></textarea>
<p v-if="validation.message">{{validation.message.msg}}</p>
</div>
</div>
<div class="col-12">
<div class="formRow center-align">
<button type="submit" class="btn btn-primary-fill">{{staticData.t13}}</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
</div>
<div class="page contact--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="row">
<div class="col-12 p1">
<h2 class="title">{{ staticData.t1 }}</h2>
<!-- <p>{{staticData.t2}}</p>-->
</div>
<div class="col-12 p2">
<ul>
<li>
<i class="fas fa-map-marker-alt"></i>
<span>{{ $store.state.global.address[$route.params.lang] }}</span>
</li>
<li>
<i class="fas fa-phone"></i>
<a :href="'tel:' + $store.state.global.tell">
<span>{{ staticData.t15 }}</span>
<b class="phone-number">{{ $store.state.global.tell_view }}</b>
</a>
-
<a :href="'tel:' + $store.state.global.fax">
<span>{{ staticData.t16 }}</span>
<b class="phone-number">{{ $store.state.global.fax_view }}</b>
</a>
</li>
<li>
<i class="fas fa-envelope"></i>
<a :href="'mailto:' + $store.state.global.email">{{ $store.state.global.email }}</a>
</li>
</ul>
</div>
<div class="col-12 p3">
<hr>
<b>{{ staticData.t4 }}</b>
<p>{{ staticData.t5 }}</p>
<ul>
<li>
<a :href="$store.state.global.instagram_url" target="_blank">
<i class="fab fa-instagram"></i>
</a>
</li>
<li>
<a :href="$store.state.global.linkedin_url" target="_blank">
<i class="fab fa-linkedin-in"></i>
</a>
</li>
</ul>
</div>
<div class="col-12 p4">
<div class="mapouter">
<div class="gmap_canvas">
<iframe id="gmap_canvas"
src="https://maps.google.com/maps?q=%D8%A7%D8%B1%D8%A7%DA%A9%20%D8%B1%DB%8C%D9%84%20%D8%8C%D8%A7%D8%B3%D8%AA%D8%A7%D9%86%20%D9%85%D8%B1%DA%A9%D8%B2%DB%8C%D8%8C%20%D8%A7%D8%B1%D8%A7%DA%A9%D8%8C%20%D8%B4%D9%87%D8%B1%DA%A9%20%D9%82%D8%B7%D8%A8%20%D8%B5%D9%86%D8%B9%D8%AA%DB%8C%D8%8C%20%D8%AE%DB%8C%D8%A7%D8%A8%D8%A7%D9%86%20%D8%AA%D9%84%D8%A7%D8%B4%D8%8C%20%D9%87%D9%85%D8%AA&t=&z=13&ie=UTF8&iwloc=&output=embed"
frameborder="0" scrolling="no" marginheight="0" marginwidth="0">
</iframe>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="panel">
<div class="row">
<div class="col-12">
<h2>{{ staticData.t6 }}</h2>
<form class="form" @submit.prevent="upload">
<div class="row">
<div class="col-12">
<div class="formRow center-align" :class="validation.reason ? 'err' : null">
<select name="reason" v-model="formData.reason">
<option disabled selected :value="false">{{ staticData.t7 }}</option>
<option v-for="item in reasons" :key="item._id" :value="item.reason_details.fa.reason">{{ item.reason_details[$route.params.lang].reason }}</option>
</select>
<p v-if="validation.reason">{{ validation.reason.msg }}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.first_name ? 'err' : null">
<input type="text" :placeholder="staticData.t8" name="first_name" v-model="formData.first_name">
<p v-if="validation.first_name">{{ validation.first_name.msg }}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.last_name ? 'err' : null">
<input type="text" :placeholder="staticData.t9" name="last_name" v-model="formData.last_name">
<p v-if="validation.last_name">{{ validation.last_name.msg }}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.phone_number ? 'err' : null">
<input type="text" :placeholder="staticData.t10" name="phone_number" v-model="formData.phone_number">
<p v-if="validation.phone_number">{{ validation.phone_number.msg }}</p>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="formRow" :class="validation.email ? 'err' : null">
<input type="text" :placeholder="staticData.t11" name="email" v-model="formData.email">
<p v-if="validation.email">{{ validation.email.msg }}</p>
</div>
</div>
<div class="col-12">
<div class="formRow" :class="validation.message ? 'err' : null">
<textarea :placeholder="staticData.t12" name="message" v-model="formData.message"></textarea>
<p v-if="validation.message">{{ validation.message.msg }}</p>
</div>
</div>
<div class="col-12">
<div class="formRow center-align">
<button type="submit" class="btn btn-primary-fill">{{ staticData.t13 }}</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
export default {
data() {
return {
formData: {
reason: false,
first_name: '',
last_name: '',
phone_number: '',
email: '',
message: '',
locale: this.$route.params.lang
},
reasons: null,
validation: {}
}
export default {
data() {
return {
formData: {
reason: false,
first_name: '',
last_name: '',
phone_number: '',
email: '',
message: '',
locale: this.$route.params.lang
},
computed: {
staticData() {
return this.$store.state.staticData.contact[this.$route.params.lang]
}
},
methods: {
upload() {
this.validation = {}
const data = this.formData
this.$axios.post(`/api/public/contact`, data)
.then(res => {
this.$message({
message: this.staticData.t14,
type: 'success'
})
this.formData = {
reason: false,
first_name: '',
last_name: '',
phone_number: '',
email: '',
message: '',
locale: this.$route.params.lang
}
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data.message)
})
}
},
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios}) {
const reasons = await $axios.get(`/api/public/contact/reason`)
return {
reasons: reasons.data
}
}
}
reasons: null,
validation: {}
}
},
computed: {
staticData() {
return this.$store.state.staticData.contact[this.$route.params.lang]
}
},
methods: {
upload() {
this.validation = {}
const data = this.formData
this.$axios.post(`/api/public/contact`, data)
.then(res => {
this.$message({
message: this.staticData.t14,
type: 'success'
})
this.formData = {
reason: false,
first_name: '',
last_name: '',
phone_number: '',
email: '',
message: '',
locale: this.$route.params.lang
}
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data.message)
})
}
},
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios}) {
const reasons = await $axios.get(`/api/public/contact/reason`)
return {
reasons: reasons.data
}
}
}
</script>
<style>
.mapouter{
position: relative;
text-align: right;
height: 500px;
width: 100%;
}
.gmap_canvas{
overflow: hidden;
background: none !important;
height: 500px;
width: 100%;
}
#gmap_canvas{
width: 100%;
height: 100%;
}
.mapouter{
position: relative;
text-align: right;
height: 500px;
width: 100%;
}
.gmap_canvas{
overflow: hidden;
background: none !important;
height: 500px;
width: 100%;
}
#gmap_canvas{
width: 100%;
height: 100%;
}
</style>
+221 -222
View File
@@ -1,232 +1,231 @@
<template>
<div class="page home--page">
<div class="slider-container">
<div id="slider" class="anim-parallax-hero">
<div class="hero clearfix" v-for="item in slider" :key="item._id">
<div class="bg" :style="{backgroundImage: `url(${item.image})`}"></div>
<div class="txt--home">
<h1>{{item.slider_details[$route.params.lang].title}}</h1>
<p>{{item.slider_details[$route.params.lang].caption}}</p>
</div>
</div>
</div>
</div>
<section class="s1">
<div class="go-down-btn" @click="scrollDown">
<em class="fa fa-angle-double-down"></em>
</div>
<div class="container">
<div class="row">
<div class="col-12 col-md-6 title-side">
<h2 class="title title-shape">{{staticData.s1.title}}</h2>
</div>
<div class="col-12 col-md-6 caption-side">
<p>{{staticData.s1.caption}}</p>
<nuxt-link :to="{name: 'lang-about',params:{lang: $route.params.lang}}" class="btn btn-primary">{{staticData.s1.link}}</nuxt-link>
</div>
</div>
</div>
</section>
<section class="s2">
<img src="~/assets/img/home/hp-s1-i2.jpg" alt="" class="section-bg anim-parallax">
<div class="container">
<div class="panel">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h2 class="title title-shape-center">{{staticData.s1_2.t1}}</h2>
</div>
<div class="col-12">
<p>{{staticData.s1_2.t2}}</p>
<p>{{staticData.s1_2.t3}}</p>
<nuxt-link :to="{name: 'lang-about',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.s1_2.link}}</nuxt-link>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s3">
<img src="~/assets/img/home/hp-s2-i1.jpg" alt="" class="section-bg anim-parallax">
<div class="container">
<div class="panel">
<div class="container-fluid">
<div class="parts p1">
<h2 class="title title-shape-center">{{staticData.s2.t1}}</h2>
<div>
<p>{{staticData.s2.t2}}</p>
</div>
</div>
<div class="parts p2 row">
<div class="col-12 col-lg-6 order-1 order-lg-0">
<div class="txtBox">
<h2 class="title title-subtitle">{{staticData.s2.t5}}</h2>
<p>{{staticData.s2.t6}}</p>
<nuxt-link :to="{name: 'lang-services',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.s2.link1}}</nuxt-link>
</div>
</div>
<div class="col-12 col-lg-6 order-0 order-lg-1 mb-5 mb-lg-0">
<div class="imgBox imgBox-shape anim-fadeIn">
<div class="img">
<img src="~/assets/img/home/hp-s2-i2.jpg" alt="">
</div>
</div>
</div>
</div>
<div class="parts p3 row">
<div class="col-12 col-lg-6 mb-5 mb-lg-0">
<div class="imgBox imgBox-reverse imgBox-shape-reverse anim-fadeIn">
<div class="img">
<img src="~/assets/img/home/hp-s2-i3.jpg" alt="">
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="txtBox">
<h2 class="title title-subtitle">{{staticData.s2.t3}}</h2>
<p>{{staticData.s2.t4}}</p>
<nuxt-link :to="{name: 'lang-tech-gStandard',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.s2.link2}}</nuxt-link>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s4">
<img src="~/assets/img/home/hp-s3-i1.jpg" alt="" class="section-bg anim-parallax">
<div class="container clearfix">
<div class="panel">
<div class="parts p1">
<h2 class="title title-shape-center">{{staticData.s3.t1}}</h2>
<div class="col-12">
<p>{{staticData.s3.t2}}</p>
</div>
</div>
</div>
<div class="products">
<div class="parts p2 row">
<div class="col-12 col-sm-6 col-lg-4 mb-5 anim-fadeIn" v-for="(item,index) in products" :key="item._id" v-if="index <= 5">
<nuxt-link :to="{name: 'lang-products-product',params: {lang: $route.params.lang,product: item._id}}" class="product">
<div class="imgBox">
<img :src="item.cover" :alt="item.product_details[$route.params.lang].name">
</div>
<p>{{item.product_details[$route.params.lang].name}}</p>
</nuxt-link>
</div>
<div class="col-12">
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.s3.link}}</nuxt-link>
</div>
</div>
</div>
</div>
</section>
<section class="s5">
<img src="~/assets/img/home/hp-s4-i1.jpg" alt="" class="section-bg">
<div class="txt anim-parallax">
<h2 class="title title-shape">{{staticData.s4.t1}} <span>{{staticData.s4.t2}}</span></h2>
<p>{{staticData.s4.t3}}</p>
<a :href="catalog.file" target="_blank" class="btn btn-reverse-fill">{{staticData.s4.link}}</a>
</div>
</section>
<CustomersCommunication/>
<section class="s6">
<div class="container">
<div class="row">
<div class="col-2 d-none d-lg-block"></div>
<div class="col-12 col-lg-6">
<h2 class="title title-shape">{{staticData.s6.t1}}</h2>
<p>{{staticData.s6.t2}}</p>
<!-- <nuxt-link :to="{name: 'lang-calculation',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.s6.link1}}</nuxt-link>-->
<a @click.prevent="notAvailable" href="" class="btn btn-primary">{{staticData.s6.link1}}</a>
<a @click.prevent="notAvailable" :href="calc_app_link" target="_blank" class="btn btn-primary-fill">{{staticData.s6.link2}}</a>
</div>
<div class="col-2 img-side d-none d-lg-block">
<img src="~/assets/img/home/hp-s6-i1.png" class="anim-fadeIn" alt="">
</div>
</div>
</div>
</section>
</div>
<div class="page home--page">
<div class="slider-container">
<div id="slider" class="anim-parallax-hero">
<div class="hero clearfix" v-for="item in slider" :key="item._id">
<div class="bg" :style="{backgroundImage: `url(${item.image})`}"></div>
<div class="txt--home">
<h1>{{ item.slider_details[$route.params.lang].title }}</h1>
<p>{{ item.slider_details[$route.params.lang].caption }}</p>
</div>
</div>
</div>
</div>
<section class="s1">
<div class="go-down-btn" @click="scrollDown">
<em class="fa fa-angle-double-down"></em>
</div>
<div class="container">
<div class="row">
<div class="col-12 col-md-6 title-side">
<h2 class="title title-shape">{{ staticData.s1.title }}</h2>
</div>
<div class="col-12 col-md-6 caption-side">
<p>{{ staticData.s1.caption }}</p>
<nuxt-link :to="{name: 'lang-about',params:{lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s1.link }}</nuxt-link>
</div>
</div>
</div>
</section>
<section class="s2">
<img src="~/assets/img/home/hp-s1-i2.jpg" alt="" class="section-bg anim-parallax">
<div class="container">
<div class="panel">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h2 class="title title-shape-center">{{ staticData.s1_2.t1 }}</h2>
</div>
<div class="col-12">
<p>{{ staticData.s1_2.t2 }}</p>
<p>{{ staticData.s1_2.t3 }}</p>
<nuxt-link :to="{name: 'lang-about',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s1_2.link }}</nuxt-link>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s3">
<img src="~/assets/img/home/hp-s2-i1.jpg" alt="" class="section-bg anim-parallax">
<div class="container">
<div class="panel">
<div class="container-fluid">
<div class="parts p1">
<h2 class="title title-shape-center">{{ staticData.s2.t1 }}</h2>
<div>
<p>{{ staticData.s2.t2 }}</p>
</div>
</div>
<div class="parts p2 row">
<div class="col-12 col-lg-6 order-1 order-lg-0">
<div class="txtBox">
<h2 class="title title-subtitle">{{ staticData.s2.t5 }}</h2>
<p>{{ staticData.s2.t6 }}</p>
<nuxt-link :to="{name: 'lang-services',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s2.link1 }}</nuxt-link>
</div>
</div>
<div class="col-12 col-lg-6 order-0 order-lg-1 mb-5 mb-lg-0">
<div class="imgBox imgBox-shape anim-fadeIn">
<div class="img">
<img src="~/assets/img/home/hp-s2-i2.jpg" alt="">
</div>
</div>
</div>
</div>
<div class="parts p3 row">
<div class="col-12 col-lg-6 mb-5 mb-lg-0">
<div class="imgBox imgBox-reverse imgBox-shape-reverse anim-fadeIn">
<div class="img">
<img src="~/assets/img/home/hp-s2-i3.jpg" alt="">
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="txtBox">
<h2 class="title title-subtitle">{{ staticData.s2.t3 }}</h2>
<p>{{ staticData.s2.t4 }}</p>
<nuxt-link :to="{name: 'lang-tech-gStandard',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s2.link2 }}</nuxt-link>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s4">
<img src="~/assets/img/home/hp-s3-i1.jpg" alt="" class="section-bg anim-parallax">
<div class="container clearfix">
<div class="panel">
<div class="parts p1">
<h2 class="title title-shape-center">{{ staticData.s3.t1 }}</h2>
<div class="col-12">
<p>{{ staticData.s3.t2 }}</p>
</div>
</div>
</div>
<div class="products">
<div class="parts p2 row">
<div class="col-12 col-sm-6 col-lg-4 mb-5 anim-fadeIn" v-for="item in favoriteProducts" :key="item._id">
<nuxt-link :to="{name: 'lang-products-product',params: {lang: $route.params.lang,product: item._id}}" class="product">
<div class="imgBox">
<img :src="item.thumb" :alt="item.product_details[$route.params.lang].name">
</div>
<p>{{ item.product_details[$route.params.lang].name }}</p>
</nuxt-link>
</div>
<div class="col-12">
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s3.link }}</nuxt-link>
</div>
</div>
</div>
</div>
</section>
<section class="s5">
<img src="~/assets/img/home/hp-s4-i1.jpg" alt="" class="section-bg">
<div class="txt anim-parallax">
<h2 class="title title-shape">{{ staticData.s4.t1 }} <span>{{ staticData.s4.t2 }}</span></h2>
<p>{{ staticData.s4.t3 }}</p>
<a v-if="catalog && catalog.file" :href="catalog.file[$route.params.lang]" target="_blank" class="btn btn-reverse-fill">{{ staticData.s4.link }}</a>
</div>
</section>
<CustomersCommunication/>
<section class="s6">
<div class="container">
<div class="row">
<div class="col-2 d-none d-lg-block"></div>
<div class="col-12 col-lg-6">
<h2 class="title title-shape">{{ staticData.s6.t1 }}</h2>
<p>{{ staticData.s6.t2 }}</p>
<nuxt-link :to="{name: 'lang-calculation',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s6.link1 }}</nuxt-link>
<a @click.prevent="notAvailable" :href="calc_app_link" target="_blank" class="btn btn-primary-fill">{{ staticData.s6.link2 }}</a>
</div>
<div class="col-2 img-side d-none d-lg-block">
<img src="~/assets/img/home/hp-s6-i1.png" class="anim-fadeIn" alt="">
</div>
</div>
</div>
</section>
</div>
</template>
<script>
if (process.client) require('slick-carousel')
import {fadeInAnimation, parallaxAnimation, parallaxAnimation_hero} from '~/mixins/animations'
if (process.client) require('slick-carousel')
import {fadeInAnimation, parallaxAnimation, parallaxAnimation_hero} from '~/mixins/animations'
export default {
data() {
return {
slider: null,
products: null,
catalog: null,
calc_app_link: this.$store.state.staticData.calc_app_link,
validation: []
}
},
computed: {
staticData() {
return this.$store.state.staticData.homePage[this.$route.params.lang]
}
},
methods: {
scrollDown() {
this.$gsap.to(window, {scrollTo: {y: $('.home--page .s1'), offsetY: 90}, duration: 0.9, ease: 'power4.inOut'})
},
notAvailable() {
this.$alert(this.$route.params.lang === 'fa' ? 'این بخش فعلا در دسترس نیست' : 'This section is currently unavailable', '', {
confirmButtonText: 'OK',
})
}
},
mixins: [fadeInAnimation, parallaxAnimation, parallaxAnimation_hero],
mounted() {
/////////////////////////////////////// carousel
$('#slider').slick({
slidesToShow: 1,
rtl: this.$route.params.lang === 'fa',
dots: true,
autoplay: true,
autoplaySpeed: 6000,
responsive: [
{
breakpoint: 768,
settings: {
arrows: false
}
}
]
})
},
head() {
return {
title: this.staticData.title
}
},
async asyncData({$axios}) {
const slider = await $axios.get('/api/public/slider')
const products = await $axios.get(`/api/public/products`)
const catalog = await $axios.get('/api/public/catalog')
export default {
data() {
return {
slider: null,
favoriteProducts: null,
catalog: null,
calc_app_link: this.$store.state.staticData.calc_app_link,
validation: []
}
},
computed: {
staticData() {
return this.$store.state.staticData.homePage[this.$route.params.lang]
}
},
methods: {
scrollDown() {
this.$gsap.to(window, {scrollTo: {y: $('.home--page .s1'), offsetY: 90}, duration: 0.9, ease: 'power4.inOut'})
},
notAvailable() {
this.$alert(this.$route.params.lang === 'fa' ? 'این بخش فعلا در دسترس نیست' : 'This section is currently unavailable', '', {
confirmButtonText: 'OK',
})
}
},
mixins: [fadeInAnimation, parallaxAnimation, parallaxAnimation_hero],
mounted() {
/////////////////////////////////////// carousel
$('#slider').slick({
slidesToShow: 1,
rtl: this.$route.params.lang === 'fa',
dots: true,
autoplay: true,
autoplaySpeed: 6000,
responsive: [
{
breakpoint: 768,
settings: {
arrows: false
}
}
]
})
},
head() {
return {
title: this.staticData.title
}
},
async asyncData({$axios}) {
const slider = await $axios.get('/api/public/slider')
const favoriteProducts = await $axios.get(`/api/public/favoriteProducts`)
const catalog = await $axios.get('/api/public/catalog')
return {
slider: slider.data,
products: products.data,
catalog: catalog.data
}
}
}
return {
slider: slider.data,
favoriteProducts: favoriteProducts.data,
catalog: catalog.data
}
}
}
</script>
<style scoped>
.footer{
background: #F0F0F0 !important;
}
.footer{
background: #F0F0F0 !important;
}
</style>
+178 -176
View File
@@ -1,183 +1,185 @@
<template>
<div class="page product-details--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{productDetails.page_title}}</h2>
<p>{{productDetails.page_description}}</p>
<div class="image-preview">
<img :src="product.cover" class="anim-fadeIn" ref="preview" :alt="productDetails.name">
</div>
</div>
<div class="images-carousel anim-fadeIn">
<div id="images">
<div class="imgBox">
<img :src="product.cover" :alt="productDetails.name" @click="view(product.cover)">
</div>
<div class="imgBox" v-for="item in product.images" :key="item._id">
<img :src="item.image" :alt="productDetails.name" @click="view(item.image)">
</div>
</div>
</div>
</div>
</section>
<section class="s2" v-if="product.more_section">
<div class="container">
<div class="panel">
<div class="parts p1">
<h2 class="title title-shape-center">{{staticData.t1}}</h2>
</div>
<!-- image left -->
<div class="parts row align-items-center">
<div class="col-6">
<h2 class="title title-subtitle">{{productDetails.more_title1}}</h2>
<p>{{productDetails.more_description1}}</p>
</div>
<div class="col-6">
<div class="imgBox imgBox-shape anim-fadeIn">
<img :src="product.more_section_image1" :alt="productDetails.more_title1">
</div>
</div>
</div>
<!-- image right -->
<div class="parts row align-items-center">
<div class="col-6">
<div class="imgBox imgBox-reverse imgBox-shape-reverse anim-fadeIn">
<img :src="product.more_section_image2" :alt="productDetails.more_title2">
</div>
</div>
<div class="col-6">
<h2 class="title title-subtitle">{{productDetails.more_title2}}</h2>
<p>{{productDetails.more_description2}}</p>
</div>
</div>
</div>
</div>
</section>
<section class="s3"
v-if="!product.render_image1.includes('undefined') ||
!product.render_image2.includes('undefined') ||
<div class="page product-details--page latin-digits">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{ productDetails.page_title }}</h2>
<p>{{ productDetails.page_description }}</p>
<div class="image-preview">
<img :src="product.cover" class="anim-fadeIn" ref="preview" :alt="productDetails.name">
<div class="images-carousel anim-fadeIn" v-if="product.images.length">
<div id="images">
<div class="imgBox">
<img class="selected" :src="product.cover" :alt="productDetails.name" @click="view(product.cover)">
</div>
<div class="imgBox" v-for="item in product.images" :key="item._id">
<img :src="item.image" :alt="productDetails.name" @click="view(item.image)">
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s2" v-if="product.more_section">
<div class="container">
<div class="panel">
<div class="parts p1">
<h2 class="title title-shape-center">{{ staticData.t1 }}</h2>
</div>
<!-- image left -->
<div class="parts row align-items-center">
<div class="col-6">
<h2 class="title title-subtitle">{{ productDetails.more_title1 }}</h2>
<p>{{ productDetails.more_description1 }}</p>
</div>
<div class="col-6">
<div class="imgBox imgBox-shape anim-fadeIn">
<img :src="product.more_section_image1" :alt="productDetails.more_title1">
</div>
</div>
</div>
<!-- image right -->
<div class="parts row align-items-center">
<div class="col-6">
<div class="imgBox imgBox-reverse imgBox-shape-reverse anim-fadeIn">
<img :src="product.more_section_image2" :alt="productDetails.more_title2">
</div>
</div>
<div class="col-6">
<h2 class="title title-subtitle">{{ productDetails.more_title2 }}</h2>
<p>{{ productDetails.more_description2 }}</p>
</div>
</div>
</div>
</div>
</section>
<section class="s3"
v-if="product.render_image1 ||
product.render_image2 ||
product.download_section">
<div class="container">
<div class="panel">
<div class="parts p1" v-if="!product.render_image1.includes('undefined') || !product.render_image1.includes('undefined')">
<h2 class="title">{{staticData.t2}}</h2>
<p>{{staticData.t3}}</p>
</div>
<div class="row parts p2" v-if="!product.render_image1.includes('undefined') || !product.render_image2.includes('undefined')">
<div class="col-12 col-sm-6 mb-5">
<img :src="product.render_image1" class="anim-fadeIn" :alt="productDetails.name" v-if="!product.render_image1.includes('undefined')">
<p v-if="!product.render_image1.includes('undefined')">{{productDetails.render_caption1}}</p>
</div>
<div class="col-12 col-sm-6 mb-5">
<img :src="product.render_image2" class="anim-fadeIn" :alt="productDetails.name" v-if="!product.render_image2.includes('undefined')">
<p v-if="!product.render_image2.includes('undefined')">{{productDetails.render_caption2}}</p>
</div>
<div class="col-12 mb-5">
<img :src="product.chart_image" class="anim-fadeIn" :alt="productDetails.name" v-if="!product.chart_image.includes('undefined')">
</div>
</div>
<div class="row parts p3" v-if="productDetails.chart_title">
<div class="col-12">
<h2 class="title">{{productDetails.chart_title}}</h2>
<p>{{productDetails.chart_description}}</p>
</div>
</div>
<div class="row parts p4" v-if="product.download_section">
<div class="col-12">
<h2>{{staticData.t4}}</h2>
<div class="files">
<div class="file anim-fadeIn" v-for="item in product.pdf_files" :key="item._id">
<pdf-icon/>
<p>{{item.pdf_details[$route.params.lang].name}}</p>
<a :href="item.file" :download="item.pdf_details[$route.params.lang].name" target="_blank" class="btn btn-primary-fill">{{staticData.t5}}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s4">
<div class="container">
<div class="row">
<div class="col-12">
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.t6}}</nuxt-link>
</div>
</div>
</div>
</section>
</div>
<div class="container">
<div class="panel">
<div class="parts p1" v-if="product.render_image1 || product.render_image1">
<h2 class="title">{{ staticData.t2 }}</h2>
<p>{{ staticData.t3 }}</p>
</div>
<div class="row parts p2" v-if="product.render_image1 || product.render_image2">
<div class="col-12 col-sm-6 mb-5">
<img :src="product.render_image1" class="anim-fadeIn" :alt="productDetails.name" v-if="product.render_image1">
<p v-if="product.render_image1">{{ productDetails.render_caption1 }}</p>
</div>
<div class="col-12 col-sm-6 mb-5">
<img :src="product.render_image2" class="anim-fadeIn" :alt="productDetails.name" v-if="product.render_image2">
<p v-if="product.render_image2">{{ productDetails.render_caption2 }}</p>
</div>
</div>
<div class="row parts p3" v-if="productDetails.chart_title">
<div class="col-12">
<h2 class="title">{{ productDetails.chart_title }}</h2>
<p>{{ productDetails.chart_description }}</p>
</div>
<div class="col-12 mb-5 mt-5">
<img :src="product.chart_image" class="anim-fadeIn" :alt="productDetails.name" v-if="product.chart_image">
</div>
</div>
<div class="row parts p4" v-if="product.download_section">
<div class="col-12">
<h2>{{ staticData.t4 }}</h2>
<div class="files">
<div class="file anim-fadeIn" v-for="item in product.pdf_files" :key="item._id">
<pdf-icon/>
<p>{{ item.pdf_details[$route.params.lang].name }}</p>
<a :href="item.file[$route.params.lang]" :download="item.pdf_details[$route.params.lang].name" target="_blank" class="btn btn-primary-fill">{{ staticData.t5 }}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s4">
<div class="container">
<div class="row">
<div class="col-12">
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t6 }}</nuxt-link>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
if (process.client) require('slick-carousel')
import {fadeInAnimation} from "~/mixins/animations"
if (process.client) require('slick-carousel')
import {fadeInAnimation} from "~/mixins/animations"
export default {
data() {
return {
product: null
}
},
computed: {
staticData() {
return this.$store.state.staticData.products_details[this.$route.params.lang]
},
productDetails() {
return this.product.product_details[this.$route.params.lang]
}
},
methods: {
view(image) {
// console.log(image)
this.$refs.preview.src = image
}
},
mixins: [fadeInAnimation],
mounted() {
$('#images').slick({
slidesToShow: 4,
rtl: this.$route.params.lang === 'fa',
infinite: false,
responsive: [
{
breakpoint: 768,
settings: {
slidesToShow: 3
}
},
{
breakpoint: 575,
settings: {
slidesToShow: 2
}
}
]
})
},
head() {
return {
title: this.product.product_details[this.$route.params.lang].name
}
},
async asyncData({$axios, params}) {
let product = await $axios.get(`/api/public/product/${params.product}`)
let productCategories = await $axios.get(`/api/public/productCategories`)
return {
product: product.data,
productCategories: productCategories.data
}
}
}
export default {
data() {
return {
product: null
}
},
computed: {
staticData() {
return this.$store.state.staticData.products_details[this.$route.params.lang]
},
productDetails() {
return this.product.product_details[this.$route.params.lang]
}
},
methods: {
view(image) {
this.$refs.preview.src = image
$('.product-details--page #images img').removeClass('selected')
$(event.target).addClass('selected')
}
},
mixins: [fadeInAnimation],
mounted() {
$('#images').slick({
slidesToShow: 4,
rtl: this.$route.params.lang === 'fa',
infinite: false,
responsive: [
{
breakpoint: 768,
settings: {
slidesToShow: 3
}
},
{
breakpoint: 575,
settings: {
slidesToShow: 2
}
}
]
})
},
head() {
return {
title: this.product.product_details[this.$route.params.lang].name
}
},
async asyncData({$axios, params}) {
let product = await $axios.get(`/api/public/product/${params.product}`)
let productCategories = await $axios.get(`/api/public/productCategories`)
return {
product: product.data,
productCategories: productCategories.data
}
}
}
</script>
+113 -113
View File
@@ -1,121 +1,121 @@
<template>
<div class="page products--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{staticData.s1.t1}}</h2>
<p>{{staticData.s1.t2}}</p>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="filters anim-fadeIn">
<h2 class="title title-subtitle">{{staticData.s2.t1}}</h2>
<ul>
<li @click="filtering(false)">
<p class="active">{{staticData.s2.t3}}</p>
</li>
<li
v-for="item in productCategories"
:key="item._id"
@click="filtering(item._id)">
<p>{{item.category_details[$route.params.lang].name}}</p>
</li>
</ul>
</div>
<div class="row products-container" v-if="filtered_products.length">
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-5 anim-fadeIn" v-for="item in filtered_products" :key="item._id">
<nuxt-link :to="{name: 'lang-products-product',params: {lang: $route.params.lang,product: item._id}}" class="product">
<div class="imgBox">
<img :src="item.cover" :alt="item.product_details[$route.params.lang].name">
</div>
<h4>{{item.product_details[$route.params.lang].name}}</h4>
<p>{{item.product_details[$route.params.lang].short_description}}</p>
</nuxt-link>
</div>
</div>
<div class="row" v-else>
<div class="col-12 products-container">
<p class="no-product anim-fadeIn">{{staticData.s2.t2}}</p>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<div class="panel anim-fadeIn">
<h2 class="title title-shape-center">
{{staticData.s3.t1}}
<span class="subtitle">{{staticData.s3.t2}}</span>
</h2>
<p>{{staticData.s3.t3}}</p>
<a :href="catalog.file" target="_blank" class="btn btn-reverse-fill">{{staticData.s3.t4}}</a>
</div>
</div>
</section>
</div>
<div class="page products--page latin-digits">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{ staticData.s1.t1 }}</h2>
<p>{{ staticData.s1.t2 }}</p>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="filters anim-fadeIn">
<h2 class="title title-subtitle">{{ staticData.s2.t1 }}</h2>
<ul>
<li @click="filtering(false)">
<p class="active">{{ staticData.s2.t3 }}</p>
</li>
<li
v-for="item in productCategories"
:key="item._id"
@click="filtering(item._id)">
<p>{{ item.category_details[$route.params.lang].name }}</p>
</li>
</ul>
</div>
<div class="row products-container" v-if="filtered_products.length">
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-5 anim-fadeIn" v-for="item in filtered_products" :key="item._id">
<nuxt-link :to="{name: 'lang-products-product',params: {lang: $route.params.lang,product: item._id}}" class="product">
<div class="imgBox">
<img :src="item.thumb" :alt="item.product_details[$route.params.lang].name">
</div>
<h4>{{ item.product_details[$route.params.lang].name }}</h4>
<p>{{ item.product_details[$route.params.lang].short_description }}</p>
</nuxt-link>
</div>
</div>
<div class="row" v-else>
<div class="col-12 products-container">
<p class="no-product anim-fadeIn">{{ staticData.s2.t2 }}</p>
</div>
</div>
</div>
</section>
<section class="s3">
<div class="container">
<div class="panel anim-fadeIn">
<h2 class="title title-shape-center">
{{ staticData.s3.t1 }}
<span class="subtitle">{{ staticData.s3.t2 }}</span>
</h2>
<p>{{ staticData.s3.t3 }}</p>
<a v-if="catalog && catalog.file" :href="catalog.file[$route.params.lang]" target="_blank" class="btn btn-reverse-fill">{{ staticData.s3.t4 }}</a>
</div>
</div>
</section>
</div>
</template>
<script>
import {fadeInAnimation} from "~/mixins/animations"
import {fadeInAnimation} from "~/mixins/animations"
export default {
data() {
return {
products: null,
productCategories: null,
catalog: null,
filter: false
}
},
computed: {
staticData() {
return this.$store.state.staticData.products[this.$route.params.lang]
},
filtered_products() {
if (!this.filter) return this.products
else return this.products.filter(item => item.category === this.filter)
}
},
methods: {
filtering(key) {
$('.products--page .filters p').removeClass('active')
$(event.target).addClass('active')
export default {
data() {
return {
products: null,
productCategories: null,
catalog: null,
filter: false
}
},
computed: {
staticData() {
return this.$store.state.staticData.products[this.$route.params.lang]
},
filtered_products() {
if (!this.filter) return this.products
else return this.products.filter(item => item.category === this.filter)
}
},
methods: {
filtering(key) {
$('.products--page .filters p').removeClass('active')
$(event.target).addClass('active')
this.$gsap.timeline({
yoyo: true,
repeat: 1
})
.to($('.products--page .products-container'),
{
opacity: 0,
duration: 0.3,
onComplete: () => {
this.filter = key
}
})
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios, store}) {
const products = await $axios.get(`/api/public/products`)
const productCategories = await $axios.get(`/api/public/productCategories`)
const catalog = await $axios.get('/api/public/catalog')
this.$gsap.timeline({
yoyo: true,
repeat: 1
})
.to($('.products--page .products-container'),
{
opacity: 0,
duration: 0.3,
onComplete: () => {
this.filter = key
}
})
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios, store}) {
const products = await $axios.get(`/api/public/products`)
const productCategories = await $axios.get(`/api/public/productCategories`)
const catalog = await $axios.get('/api/public/catalog')
return {
products: products.data,
productCategories: productCategories.data,
catalog: catalog.data
}
}
}
return {
products: products.data,
productCategories: productCategories.data,
catalog: catalog.data
}
}
}
</script>
+111 -111
View File
@@ -1,117 +1,117 @@
<template>
<div class="page projects--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{staticData.t1}}</h2>
<p>{{staticData.t2}}</p>
<p>{{staticData.t3}}</p>
<div class="projects" v-if="projects.length">
<div class="project anim-fadeIn" v-for="(item,index) in projects" :key="item._id">
<div :id="`project_${index}`">
<div class="imgBox" v-for="image in item.images" :key="image._id">
<img class="bg" :src="image.image" alt="">
<img class="img" :src="image.image" alt="">
</div>
</div>
<div class="caption">
<h4>{{item.project_details[$route.params.lang].name}}</h4>
<p class="description">{{item.project_details[$route.params.lang].description}}</p>
<p>
<span>{{staticData.t6}}</span>
<span>{{jDate(item.date)}}</span>
</p>
</div>
</div>
</div>
<div class="no-project" v-else>
<div class="container">
<div class="row">
<div class="col-12">
<p>{{staticData.t7}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{staticData.t4}}</h2>
<nuxt-link :to="{name: 'lang-contact',params:{lang: $route.params.lang}}" class="btn btn-reverse-fill">{{staticData.t5}}</nuxt-link>
</div>
</div>
</div>
</section>
</div>
<div class="page projects--page">
<Hero :title="staticData.hero"/>
<section class="s1">
<div class="container">
<div class="panel">
<h2 class="title">{{ staticData.t1 }}</h2>
<p>{{ staticData.t2 }}</p>
<p>{{ staticData.t3 }}</p>
<div class="projects" v-if="projects.length">
<div class="project anim-fadeIn" v-for="(item,index) in projects" :key="item._id">
<div :id="`project_${index}`">
<div class="imgBox" v-for="image in item.images" :key="image._id">
<img class="bg" :src="image.image" alt="">
<img class="img" :src="image.image" alt="">
</div>
</div>
<div class="caption">
<h4>{{ item.project_details[$route.params.lang].name }}</h4>
<p class="description">{{ item.project_details[$route.params.lang].description }}</p>
<p>
<span>{{ staticData.t6 }}</span>
<span>{{ jDate(item.date) }}</span>
</p>
</div>
</div>
</div>
<div class="no-project" v-else>
<div class="container">
<div class="row">
<div class="col-12">
<p>{{ staticData.t7 }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{ staticData.t4 }}</h2>
<nuxt-link :to="{name: 'lang-contact',params:{lang: $route.params.lang}}" class="btn btn-reverse-fill">{{ staticData.t5 }}</nuxt-link>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
if (process.client) require('slick-carousel')
import moment from "moment-jalaali"
import {fadeInAnimation} from "~/mixins/animations"
if (process.client) require('slick-carousel')
import moment from "moment-jalaali"
import {fadeInAnimation} from "~/mixins/animations"
export default {
data() {
return {
projects: null
}
},
computed: {
staticData() {
return this.$store.state.staticData.projects[this.$route.params.lang]
}
},
methods: {
jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD')
else return date.split(' ')[0]
}
},
mixins: [fadeInAnimation],
mounted() {
this.projects.forEach((item, index) => {
$(`#project_${index}`).slick({
slidesToShow: 1,
centerMode: true,
centerPadding: '150px',
infinite: true,
arrows: true,
responsive: [
{
breakpoint: 768,
settings: {
slidesToShow: 2,
centerMode: false
}
},
{
breakpoint: 575,
settings: {
slidesToShow: 1,
centerMode: false
}
}
]
})
})
},
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios}) {
const projects = await $axios.get(`/api/public/projects`)
return {
projects: projects.data
}
}
}
export default {
data() {
return {
projects: null
}
},
computed: {
staticData() {
return this.$store.state.staticData.projects[this.$route.params.lang]
}
},
methods: {
jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).jYear()
else return moment(date).year()
}
},
mixins: [fadeInAnimation],
mounted() {
this.projects.forEach((item, index) => {
$(`#project_${index}`).slick({
slidesToShow: 1,
centerMode: true,
centerPadding: '150px',
infinite: true,
arrows: true,
responsive: [
{
breakpoint: 768,
settings: {
slidesToShow: 2,
centerMode: false
}
},
{
breakpoint: 575,
settings: {
slidesToShow: 1,
centerMode: false
}
}
]
})
})
},
head() {
return {
title: this.staticData.hero
}
},
async asyncData({$axios}) {
const projects = await $axios.get(`/api/public/projects`)
return {
projects: projects.data
}
}
}
</script>
+43 -43
View File
@@ -1,49 +1,49 @@
<template>
<div class="page tech-info--page">
<Hero :title="staticData.title"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="content gDesign">
<h2 class="first">{{staticData.t1}}</h2>
<p>{{staticData.t2}}</p>
<p v-html="staticData.t3"></p>
<p>{{staticData.t4}}</p>
<br>
<br>
<p>{{staticData.t5}}</p>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{staticData.t6}}</h2>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.t7}}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
<div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="content gDesign">
<h2 class="first">{{ staticData.t1 }}</h2>
<p>{{ staticData.t2 }}</p>
<p v-html="staticData.t3"></p>
<p>{{ staticData.t4 }}</p>
<br>
<br>
<p>{{ staticData.t5 }}</p>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{ staticData.t6 }}</h2>
<nuxt-link :to="{name: 'lang-calculation',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t7 }}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
</template>
<script>
import {fadeInAnimation} from "~/mixins/animations"
import {fadeInAnimation} from "~/mixins/animations"
export default {
computed: {
staticData() {
return this.$store.state.staticData.gDesign[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.title
}
},
}
export default {
computed: {
staticData() {
return this.$store.state.staticData.gDesign[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.title
}
},
}
</script>
+61 -73
View File
@@ -1,79 +1,67 @@
<template>
<div class="page tech-info--page">
<Hero :title="staticData.title"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="content gStandard">
<h2 class="first">{{staticData.t1}}</h2>
<p>{{staticData.t2}}</p>
<h2>{{staticData.t3}}</h2>
<p>{{staticData.t4}}</p>
<p>{{staticData.t5}}</p>
<h2>{{staticData.t6}}</h2>
<p>{{staticData.t7}}</p>
<img class="i1 anim-fadeIn" src="~/assets/img/tech-info/g-standard.png" alt="">
<h2>{{staticData.t8}}</h2>
<p>{{staticData.t9}}</p>
<img class="i2 anim-fadeIn" src="~/assets/img/tech-info/DIN24537.png" alt="">
<h2>{{staticData.t10}}</h2>
<p>{{staticData.t11}}</p>
<p>{{staticData.t12}}</p>
<p>{{staticData.t13}}</p>
<ul>
<li>
<p>{{staticData.t14}}</p>
</li>
<li>
<p>{{staticData.t15}}</p>
</li>
<li>
<p>{{staticData.t16}}</p>
</li>
<li>
<p>{{staticData.t17}}</p>
</li>
<li>
<p>{{staticData.t18}}</p>
</li>
</ul>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{staticData.t19}}</h2>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.t20}}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
<div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="content gStandard">
<h2 class="first">{{ staticData.t1 }}</h2>
<p>{{ staticData.t2 }}</p>
<h2>{{ staticData.t3 }}</h2>
<p>{{ staticData.t4 }}</p>
<p>{{ staticData.t5 }}</p>
<h2>{{ staticData.t6 }}</h2>
<p>{{ staticData.t7 }}</p>
<img class="i1 anim-fadeIn" src="~/assets/img/tech-info/g-standard.png" alt="">
<h2>{{ staticData.t8 }}</h2>
<p>{{ staticData.t9 }}</p>
<img class="i2 anim-fadeIn" src="~/assets/img/tech-info/DIN24537.png" alt="">
<h2>{{ staticData.t10 }}</h2>
<p>{{ staticData.t11 }}</p>
<p>{{ staticData.t12 }}</p>
<p>{{ staticData.t13 }}</p>
<ul>
<li v-for="item in $store.state.staticData.about.en.s4" :key="item.title">
<a :href="`/standards_pdf/${item.link.url}`" download target="_blank">{{ item.title }}</a>
</li>
</ul>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{ staticData.t19 }}</h2>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t20 }}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
</template>
<script>
import {fadeInAnimation} from "~/mixins/animations"
import {fadeInAnimation} from "~/mixins/animations"
export default {
computed: {
staticData() {
return this.$store.state.staticData.gStandard[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.title
}
}
}
export default {
computed: {
staticData() {
return this.$store.state.staticData.gStandard[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.title
}
}
}
</script>
+2 -2
View File
@@ -1,5 +1,5 @@
<template>
<div class="page tech-info--page">
<div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/>
<section class="s1">
<div class="container">
@@ -51,7 +51,7 @@
<span>{{staticData.t22}}</span>
</p>
<p>{{staticData.t23}}</p>
<div class="imgBox anim-fadeIn">
<img src="~/assets/img/tech-info/ti-Model-4.jpg" alt="">
<p>{{staticData.t24}}</p>
+81 -71
View File
@@ -1,77 +1,87 @@
<template>
<div class="page tech-info--page">
<Hero :title="staticData.title"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="content gUsage">
<h2 class="first">{{staticData.t1}}</h2>
<p v-html="staticData.t2"></p>
<p>{{staticData.t3}}</p>
<p>{{staticData.t4}}</p>
<p>{{staticData.t5}}</p>
<ul>
<li>
<p>{{staticData.t6}}</p>
</li>
<li>
<p>{{staticData.t7}}</p>
</li>
<li>
<p>{{staticData.t8}}</p>
</li>
<li>
<p>{{staticData.t9}}</p>
</li>
<li>
<p>{{staticData.t10}}</p>
</li>
<li>
<p>{{staticData.t11}}</p>
</li>
<li>
<p>{{staticData.t12}}</p>
</li>
<li>
<p>{{staticData.t13}}</p>
</li>
<li>
<p>{{staticData.t14}}</p>
</li>
</ul>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{staticData.t15}}</h2>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.t16}}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
<div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/>
<section class="s1">
<div class="container">
<div class="panel">
<div class="content gUsage">
<h2 class="first">{{ staticData.t1 }}</h2>
<p v-html="staticData.t2"></p>
<p>{{ staticData.t3 }}</p>
<p>{{ staticData.t4 }}</p>
<p>{{ staticData.t5 }}</p>
<ul>
<li>
<p>{{ staticData.t6 }}</p>
</li>
<li>
<p>{{ staticData.t7 }}</p>
</li>
<li>
<p>{{ staticData.t8 }}</p>
</li>
<li>
<p>{{ staticData.t9 }}</p>
</li>
<li>
<p>{{ staticData.t10 }}</p>
</li>
<li>
<p>{{ staticData.t11 }}</p>
</li>
<li>
<p>{{ staticData.t12 }}</p>
</li>
<li>
<p>{{ staticData.t13 }}</p>
</li>
<li>
<p>{{ staticData.t14 }}</p>
</li>
</ul>
<h2 class="first mt-5">{{ staticData.t17 }}</h2>
<div class="images">
<img src="~/assets/img/grating-usage/4.jpg" :alt="staticData.title">
<img src="~/assets/img/grating-usage/8.jpg" :alt="staticData.title">
<img src="~/assets/img/grating-usage/13.jpg" :alt="staticData.title">
<img src="~/assets/img/grating-usage/88-wood-1.jpg" :alt="staticData.title">
<img src="~/assets/img/grating-usage/industri-2.jpg" :alt="staticData.title">
<img src="~/assets/img/grating-usage/infills-1b.jpg" :alt="staticData.title">
</div>
</div>
</div>
</div>
</section>
<section class="s2">
<div class="container">
<div class="row">
<div class="col-12">
<h2 class="title">{{ staticData.t15 }}</h2>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t16 }}</nuxt-link>
</div>
</div>
</div>
</section>
<CustomersCommunication/>
</div>
</template>
<script>
import {fadeInAnimation} from "~/mixins/animations"
import {fadeInAnimation} from "~/mixins/animations"
export default {
computed: {
staticData() {
return this.$store.state.staticData.gUsage[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.title
}
}
}
export default {
computed: {
staticData() {
return this.$store.state.staticData.gUsage[this.$route.params.lang]
}
},
mixins: [fadeInAnimation],
head() {
return {
title: this.staticData.title
}
}
}
</script>
+183 -182
View File
@@ -1,191 +1,192 @@
<template>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title">
<el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button>
<el-button type="success" @click="upload">بروزرسانی</el-button>
</admin-title-bar>
<div class="col-12">
<admin-panel>
<h2>تصویر</h2>
<el-divider></el-divider>
<img :src="post.cover" alt="" style="width: 100%">
<input type="file" ref="cover" @change="preview">
<p class="err" v-if="validation.cover">{{validation.cover.msg}}</p>
<el-form class="secondTitle">
<el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی">
<el-select v-model="post.category" placeholder="انتخاب کنید">
<el-option
v-for="item in blogCategories"
:key="item._id"
:label="item.blogCategory_details.fa.name"
:value="item._id">
</el-option>
</el-select>
<p class="err" v-if="validation.category">{{validation.category.msg}}</p>
</el-form-item>
<el-form-item prop="published" label="وضعیت انتشار پست">
<el-switch v-model="post.published" style="margin-right: 15px;"></el-switch>
</el-form-item>
</el-form>
</admin-panel>
</div>
<!-- fa -->
<div class="col-6">
<admin-panel>
<h2>فارسی</h2>
<el-divider></el-divider>
<el-form>
<el-form-item prop="title" :class="validation.fa_title ? 'is-error' : ''" label="عنوان">
<el-input v-model="post.post_details.fa.title"></el-input>
<p class="err" v-if="validation.fa_title">{{validation.fa_title.msg}}</p>
</el-form-item>
<el-form-item prop="short_description" :class="validation.fa_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="post.post_details.fa.short_description"></el-input>
<p class="err" v-if="validation.fa_short_description">{{validation.fa_short_description.msg}}</p>
</el-form-item>
</el-form>
<el-divider></el-divider>
<h6 style="margin-bottom: 30px;">توضیحات پست</h6>
<client-only>
<ckeditor v-model="post.post_details.fa.description" :config="editorConfig"></ckeditor>
<p class="err" v-if="validation.fa_description">{{validation.fa_description.msg}}</p>
</client-only>
</admin-panel>
</div>
<!-- en -->
<div class="col-6">
<admin-panel>
<h2>انگلیسی</h2>
<el-divider></el-divider>
<el-form>
<el-form-item prop="title" :class="validation.en_title ? 'is-error' : ''" label="عنوان">
<el-input v-model="post.post_details.en.title"></el-input>
<p class="err" v-if="validation.en_title">{{validation.en_title.msg}}</p>
</el-form-item>
<el-form-item prop="short_description" :class="validation.en_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="post.post_details.en.short_description"></el-input>
<p class="err" v-if="validation.en_short_description">{{validation.en_short_description.msg}}</p>
</el-form-item>
</el-form>
<el-divider></el-divider>
<h6 style="margin-bottom: 30px;">توضیحات پست</h6>
<client-only>
<ckeditor v-model="post.post_details.en.description" :config="editorConfig_en"></ckeditor>
<p class="err" v-if="validation.en_description">{{validation.en_description.msg}}</p>
</client-only>
</admin-panel>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title">
<el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button>
<el-button type="success" @click="upload">بروزرسانی</el-button>
</admin-title-bar>
<div class="col-12">
<admin-panel>
<h2>تصویر</h2>
<el-divider></el-divider>
<img :src="post.cover" alt="" style="width: 100%">
<input type="file" ref="cover" @change="preview">
<p class="err" v-if="validation.cover">{{ validation.cover.msg }}</p>
<el-form class="secondTitle">
<el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی">
<el-select v-model="post.category" placeholder="انتخاب کنید">
<el-option
v-for="item in blogCategories"
:key="item._id"
:label="item.blogCategory_details.fa.name"
:value="item._id">
</el-option>
</el-select>
<p class="err" v-if="validation.category">{{ validation.category.msg }}</p>
</el-form-item>
<el-form-item prop="published" label="وضعیت انتشار پست">
<el-switch v-model="post.published" style="margin-right: 15px;"></el-switch>
</el-form-item>
</el-form>
</admin-panel>
</div>
<!-- fa -->
<div class="col-6">
<admin-panel>
<h2>فارسی</h2>
<el-divider></el-divider>
<el-form>
<el-form-item prop="title" :class="validation.fa_title ? 'is-error' : ''" label="عنوان">
<el-input v-model="post.post_details.fa.title"></el-input>
<p class="err" v-if="validation.fa_title">{{ validation.fa_title.msg }}</p>
</el-form-item>
<el-form-item prop="short_description" :class="validation.fa_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="post.post_details.fa.short_description"></el-input>
<p class="err" v-if="validation.fa_short_description">{{ validation.fa_short_description.msg }}</p>
</el-form-item>
</el-form>
<el-divider></el-divider>
<h6 style="margin-bottom: 30px;">توضیحات پست</h6>
<client-only>
<ckeditor v-model="post.post_details.fa.description" :config="editorConfig"></ckeditor>
<p class="err" v-if="validation.fa_description">{{ validation.fa_description.msg }}</p>
</client-only>
</admin-panel>
</div>
<!-- en -->
<div class="col-6">
<admin-panel>
<h2>انگلیسی</h2>
<el-divider></el-divider>
<el-form>
<el-form-item prop="title" :class="validation.en_title ? 'is-error' : ''" label="عنوان">
<el-input v-model="post.post_details.en.title"></el-input>
<p class="err" v-if="validation.en_title">{{ validation.en_title.msg }}</p>
</el-form-item>
<el-form-item prop="short_description" :class="validation.en_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="post.post_details.en.short_description"></el-input>
<p class="err" v-if="validation.en_short_description">{{ validation.en_short_description.msg }}</p>
</el-form-item>
</el-form>
<el-divider></el-divider>
<h6 style="margin-bottom: 30px;">توضیحات پست</h6>
<client-only>
<ckeditor v-model="post.post_details.en.description" :config="editorConfig_en"></ckeditor>
<p class="err" v-if="validation.en_description">{{ validation.en_description.msg }}</p>
</client-only>
</admin-panel>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
post: null,
blogCategories: null,
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
editorConfig_en: {
language: 'en',
extraPlugins: ['bidi', 'justify']
},
validation: {},
uploading: false,
uploadProgress: null
}
export default {
data() {
return {
post: null,
blogCategories: null,
editorConfig: {
language: 'fa',
extraPlugins: ['bidi', 'justify']
},
computed: {
title() {
if (!this.uploading) {
return 'ویرایش پست'
} else {
return this.uploadProgress
}
}
editorConfig_en: {
language: 'en',
extraPlugins: ['bidi', 'justify']
},
methods: {
upload() {
this.validation = {}
const data = new FormData()
data.append('fa_title', this.post.post_details.fa.title)
data.append('en_title', this.post.post_details.en.title)
data.append('fa_description', this.post.post_details.fa.description)
data.append('en_description', this.post.post_details.en.description)
data.append('fa_short_description', this.post.post_details.fa.short_description)
data.append('en_short_description', this.post.post_details.en.short_description)
data.append('published', this.post.published)
data.append('category', this.post.category)
if (this.$refs.cover.files[0]) data.append('cover', this.$refs.cover.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor(((progressEvent.loaded / progressEvent.total) * 100)) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios.put(`/api/private/blog/${this.post._id}`, data, axiosConfig)
.then(response => {
this.$message({
message: 'پست با موفقیت بروزرسانی شد.',
type: 'success'
})
}).catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه',
})
}
})
},
preview(event) {
this.post.cover = URL.createObjectURL(event.target.files[0]);
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params}) {
const post = await $axios.get(`/api/public/blog/${params.post}`)
const blogCategories = await $axios.get(`/api/public/blogCategories`)
return {
post: post.data,
blogCategories: blogCategories.data
}
validation: {},
uploading: false,
uploadProgress: null
}
},
computed: {
title() {
if (!this.uploading) {
return 'ویرایش پست'
} else {
return this.uploadProgress
}
}
}
},
methods: {
upload() {
this.validation = {}
const data = new FormData()
data.append('fa_title', this.post.post_details.fa.title)
data.append('en_title', this.post.post_details.en.title)
data.append('fa_description', this.post.post_details.fa.description)
data.append('en_description', this.post.post_details.en.description)
data.append('fa_short_description', this.post.post_details.fa.short_description)
data.append('en_short_description', this.post.post_details.en.short_description)
data.append('published', this.post.published)
data.append('category', this.post.category)
if (this.$refs.cover.files[0]) data.append('cover', this.$refs.cover.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor(((progressEvent.loaded / progressEvent.total) * 100)) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios.put(`/api/private/blog/${this.post._id}`, data, axiosConfig)
.then(response => {
this.$message({
message: 'پست با موفقیت بروزرسانی شد.',
type: 'success'
})
this.post = response.data
}).catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه',
})
}
})
},
preview(event) {
this.post.cover = URL.createObjectURL(event.target.files[0]);
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, params}) {
const post = await $axios.get(`/api/public/blog/${params.post}`)
const blogCategories = await $axios.get(`/api/public/blogCategories`)
return {
post: post.data,
blogCategories: blogCategories.data
}
}
}
</script>
+107 -82
View File
@@ -1,90 +1,115 @@
<template>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title"></admin-title-bar>
<div class="col-6">
<admin-panel>
<h2>افزودن یا بروزرسانی کاتالوگ:</h2>
<el-divider></el-divider>
<el-form>
<input type="file" ref="file">
<el-button @click="upload" type="success">افزودن</el-button>
<p style="color: red;" v-if="validation.pdf">{{validation.pdf.msg}}</p>
</el-form>
<el-divider></el-divider>
<a v-if="catalog && catalog.file" :href="catalog.file" target="_blank">
<el-button>دانلود و مشاهده کاتالوگ فعلی</el-button>
</a>
</admin-panel>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title"></admin-title-bar>
<div class="col-12">
<admin-panel>
<h2>افزودن یا بروزرسانی کاتالوگ:</h2>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<h2>کاتالوگ فارسی:</h2>
<el-divider></el-divider>
<el-form>
<input type="file" ref="file_fa">
<el-button @click="upload('fa')" type="success">افزودن</el-button>
<p style="color: red;" v-if="validation.pdf && locale === 'fa'">{{ validation.pdf.msg }}</p>
</el-form>
<el-divider></el-divider>
<a v-if="catalog && catalog.file && catalog.file.fa" :href="catalog.file.fa" target="_blank">
<el-button>دانلود و مشاهده کاتالوگ فعلی</el-button>
</a>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<h2>کاتالوگ انگلیسی:</h2>
<el-divider></el-divider>
<el-form>
<input type="file" ref="file_en">
<el-button @click="upload('en')" type="success">افزودن</el-button>
<p style="color: red;" v-if="validation.pdf && locale === 'en'">{{ validation.pdf.msg }}</p>
</el-form>
<el-divider></el-divider>
<a v-if="catalog && catalog.file && catalog.file.en" :href="catalog.file.en" target="_blank">
<el-button>دانلود و مشاهده کاتالوگ فعلی</el-button>
</a>
</admin-panel>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
catalog: null,
validation: {},
uploading: false,
uploadProgress: null
}
},
head() {
return {
title: this.title,
}
},
computed: {
title() {
if (!this.uploading) {
return 'آپلود کاتالوگ اصلی سایت'
} else {
return this.uploadProgress
}
}
},
methods: {
upload() {
this.validation = {}
const data = new FormData()
data.append('pdf', this.$refs.file.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor(((progressEvent.loaded / progressEvent.total) * 100)) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios.post(`/api/private/catalog`, data, axiosConfig)
.then(res => {
this.$message({
type: 'success',
message: 'کاتالوگ با موفقیت آپلود شد'
})
this.$refs.file.value = null
this.catalog = res.data
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
layout: 'admin',
async asyncData({$axios}) {
let catalog = await $axios.get('/api/public/catalog')
return {
catalog: catalog.data
}
export default {
data() {
return {
catalog: null,
locale: null,
validation: {},
uploading: false,
uploadProgress: null
}
},
head() {
return {
title: this.title,
}
},
computed: {
title() {
if (!this.uploading) {
return 'آپلود کاتالوگ اصلی سایت'
} else {
return this.uploadProgress
}
}
}
},
methods: {
upload(locale) {
this.locale = locale
this.validation = {}
locale === 'fa' ? this.$refs.file_en.value = null : this.$refs.file_fa.value = null
const data = new FormData()
data.append('locale', locale)
locale === 'fa' ? data.append('pdf', this.$refs.file_fa.files[0]) : data.append('pdf', this.$refs.file_en.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor(((progressEvent.loaded / progressEvent.total) * 100)) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios.post(`/api/private/catalog`, data, axiosConfig)
.then(res => {
this.$message({
type: 'success',
message: 'کاتالوگ با موفقیت آپلود شد'
})
this.$refs.file_fa.value = null
this.$refs.file_en.value = null
this.catalog = res.data
})
.catch(err => {
if (err.response.status === 422) this.validation = err.response.data.validation
else console.log(err.response.data)
})
}
},
layout: 'admin',
async asyncData({$axios}) {
let catalog = await $axios.get('/api/public/catalog')
return {
catalog: catalog.data
}
}
}
</script>
+60 -51
View File
@@ -1,57 +1,66 @@
<template>
<div class="col-12">
<el-form @submit.native.prevent="loginFunction">
<div class="container">
<div class="row">
<div class="col-12">
<admin-panel style="width: 50%;margin: 300px auto 0">
<h1 style="text-align: center;">ورود به پنل مدیریت</h1>
<el-divider></el-divider>
<el-form-item prop="username" :class="validation.username ? 'is-error' : ''" label="نام کاربری">
<el-input v-model="login.username"></el-input>
<p class="err" v-if="validation.username">{{validation.username.msg}}</p>
</el-form-item>
<el-form-item prop="password" :class="validation.password ? 'is-error' : ''" label="پسورد">
<el-input v-model="login.password" type="password"></el-input>
<p class="err" v-if="validation.password">{{validation.password.msg}}</p>
</el-form-item>
<el-checkbox v-model="login.remember_me" style="display: block;margin-top: 30px;margin-bottom: 15px;">مرا به خاطر بسپار</el-checkbox>
<el-button size="small" native-type="submit">ورود</el-button>
</admin-panel>
<h1 v-if="$auth.loggedIn">{{$auth.user.name}}</h1>
</div>
</div>
</div>
</el-form>
</div>
<div class="col-12">
<el-form @submit.native.prevent="loginFunction">
<div class="container">
<div class="row">
<div class="col-12 d-flex justify-content-center align-items-center" style="min-height: calc(100vh - 60px);">
<admin-panel class="login">
<h1 style="text-align: center;">ورود به پنل مدیریت</h1>
<el-divider></el-divider>
<el-form-item prop="username" :class="validation.username ? 'is-error' : ''" label="نام کاربری">
<el-input v-model="login.username"></el-input>
<p class="err" v-if="validation.username">{{ validation.username.msg }}</p>
</el-form-item>
<el-form-item prop="password" :class="validation.password ? 'is-error' : ''" label="پسورد">
<el-input v-model="login.password" type="password"></el-input>
<p class="err" v-if="validation.password">{{ validation.password.msg }}</p>
</el-form-item>
<el-checkbox v-model="login.remember_me" style="display: block;margin-top: 30px;margin-bottom: 15px;">مرا به خاطر بسپار</el-checkbox>
<el-button size="small" native-type="submit">ورود</el-button>
</admin-panel>
<h1 v-if="$auth.loggedIn">{{ $auth.user.name }}</h1>
</div>
</div>
</div>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
login: {
username: '',
password: '',
remember_me: false
},
validation: {}
}
export default {
data() {
return {
login: {
username: '',
password: '',
remember_me: false
},
methods: {
loginFunction() {
this.validation = {}
this.$auth.loginWith('local', {data: this.login})
.then(res => {
this.$router.push('/admin')
})
.catch(err => {
this.validation = err.response.data.validation
})
}
},
layout: 'admin'
}
validation: {}
}
},
methods: {
loginFunction() {
this.validation = {}
this.$auth.loginWith('local', {data: this.login})
.then(res => {
this.$router.push('/admin')
})
.catch(err => {
this.validation = err.response.data.validation
})
}
},
layout: 'admin'
}
</script>
<style lang="scss" scoped>
.login {
width: 100%;
max-width: 600px;
margin: 150px auto!important;
}
</style>
File diff suppressed because it is too large Load Diff
+144 -122
View File
@@ -1,129 +1,151 @@
<template>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title">
<nuxt-link :to="{name: 'admin-products-new'}">
<el-button type="success">جدید</el-button>
</nuxt-link>
</admin-title-bar>
<div class="col-lg-12">
<admin-panel>
<el-table
:data="products"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="تصویر"
width="230">
<template slot-scope="scope">
<el-image
style="width: 100%; height: 100%"
:src="scope.row.cover"
fit="fit">
</el-image>
</template>
</el-table-column>
<el-table-column
prop="product_details.fa.name"
label="نام"
width="">
</el-table-column>
<el-table-column
prop="category"
label="دسته بندی"
width="">
<template slot-scope="scope">
{{categoryName(scope.row.category)}}
</template>
</el-table-column>
<el-table-column
label="ویرایش"
width="150"
align="left">
<template slot-scope="scope">
<el-button type="warning" plain icon="el-icon-edit" @click="edit(scope.row._id)"></el-button>
<el-button type="danger" plain icon="el-icon-delete" @click="del(scope.row._id)"></el-button>
</template>
</el-table-column>
</el-table>
</admin-panel>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title">
<nuxt-link :to="{name: 'admin-products-new'}">
<el-button type="success">جدید</el-button>
</nuxt-link>
</admin-title-bar>
<div class="col-lg-12">
<admin-panel>
<el-button-group class="filterBtns">
<el-button :type="filter ? 'success' : 'primary'" @click="filter = true">محصولات صفحه اصلی</el-button>
<el-button :type="!filter ? 'success' : 'primary'" @click="filter = false">تمام محصولات</el-button>
</el-button-group>
<el-divider></el-divider>
<el-table
:data="filteredProducts"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column
label="تصویر"
width="230">
<template slot-scope="scope">
<el-image
style="width: 100%; height: 100%"
:src="scope.row.thumb"
fit="fit">
</el-image>
</template>
</el-table-column>
<el-table-column
prop="product_details.fa.name"
label="نام"
width="">
</el-table-column>
<el-table-column
prop="category"
label="دسته بندی"
width="">
<template slot-scope="scope">
{{ categoryName(scope.row.category) }}
</template>
</el-table-column>
<el-table-column
label="ویرایش"
width="150"
align="left">
<template slot-scope="scope">
<el-button type="warning" plain icon="el-icon-edit" @click="edit(scope.row._id)"></el-button>
<el-button type="danger" plain icon="el-icon-delete" @click="del(scope.row._id)"></el-button>
</template>
</el-table-column>
</el-table>
</admin-panel>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
title: 'لیست محصولات',
products: null,
productCategories: null
}
},
head() {
return {
title: this.title,
}
},
methods: {
categoryName(id) {
let category = this.productCategories.filter(item => {
return item._id === id
})
return category[0].category_details.fa.name
},
edit(id) {
this.$router.push(`/admin/products/${id}`)
export default {
data() {
return {
title: 'لیست محصولات',
products: null,
productCategories: null,
filter: false
}
},
head() {
return {
title: this.title,
}
},
computed: {
filteredProducts() {
if (this.filter) return this.products.filter(item => item.favorite)
else return this.products
},
del(id) {
this.$confirm('این محصول حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(() => {
this.$axios.delete(`/api/private/products/${id}`)
.then(response => {
this.products = this.products.filter(item => {
return item._id !== id
})
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
});
});
}
},
layout: 'admin',
async asyncData({$axios, store}) {
let products = await $axios.get(`/api/public/products`)
let productCategories = await $axios.get(`/api/public/productCategories`)
return {
products: products.data,
productCategories: productCategories.data
}
}
}
}
},
methods: {
categoryName(id) {
let category = this.productCategories.filter(item => {
return item._id === id
})
return category[0].category_details.fa.name
},
edit(id) {
this.$router.push(`/admin/products/${id}`)
},
del(id) {
this.$confirm('این محصول حذف شود؟', 'هشدار', {
confirmButtonText: 'بله',
cancelButtonText: 'لغو',
type: 'warning'
}).then(() => {
this.$axios.delete(`/api/private/products/${id}`)
.then(response => {
this.products = this.products.filter(item => {
return item._id !== id
})
this.$message({
type: 'success',
message: 'آیتم حذف شد'
})
})
.catch(err => {
this.$message({
type: 'error',
message: err.response.data.message
})
})
}).catch(() => {
this.$message({
type: 'warning',
message: 'عملیات لغو شد'
});
});
}
},
layout: 'admin',
async asyncData({$axios, store}) {
let products = await $axios.get(`/api/public/products`)
let productCategories = await $axios.get(`/api/public/productCategories`)
return {
products: products.data,
productCategories: productCategories.data
}
}
}
</script>
<style lang="scss">
.filterBtns {
span {
color: #fff !important;
}
}
</style>
+437 -431
View File
@@ -1,439 +1,445 @@
<template>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title">
<el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button>
<el-button type="success" @click="upload">ایجاد</el-button>
</admin-title-bar>
<div class="col-6">
<admin-panel>
<p style="margin-bottom: 50px;color: green;font-weight: bold;font-size: 20px;">ابتدا محصول را ثبت کرده، سپس در مرحله بعد عکس های بیشتر و ویژگی های محصول را وارد کنید.</p>
<el-form>
<el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی">
<el-select v-model="formData.category" placeholder="انتخاب کنید">
<el-option
v-for="item in productCategories"
:key="item._id"
:label="item.category_details.fa.name"
:value="item._id">
</el-option>
</el-select>
<p class="err" v-if="validation.category">{{validation.category.msg}}</p>
</el-form-item>
<el-form-item prop="published" label="بخش دوم نمایش داده شود">
<el-switch v-model="formData.more_section" style="margin-right: 15px;"></el-switch>
</el-form-item>
<el-form-item prop="published" label="دارای فایل های قابل دانلود باشد">
<el-switch v-model="formData.download_section" style="margin-right: 15px;"></el-switch>
</el-form-item>
</el-form>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<h2>کاور</h2>
<el-divider></el-divider>
<img :src="formData.cover" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="cover" @change="previewCover">
<p class="err" v-if="validation.cover">{{validation.cover.msg}}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 470px عرض و 395px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<el-form>
<h2 style="color: #000;font-weight: bold;font-size: 30px;">فارسی</h2>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_name ? 'is-error' : ''" label="نام">
<el-input v-model="formData.product_details.fa.name"></el-input>
<p class="err" v-if="validation.fa_name">{{validation.fa_name.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="formData.product_details.fa.short_description"></el-input>
<p class="err" v-if="validation.fa_short_description">{{validation.fa_short_description.msg}}</p>
</el-form-item>
<h3>بخش اول صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_page_title ? 'is-error' : ''" label="عنوان">
<el-input type="textarea" v-model="formData.product_details.fa.page_title"></el-input>
<p class="err" v-if="validation.fa_page_title">{{validation.fa_page_title.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_page_description ? 'is-error' : ''" label="توضیحات">
<el-input type="textarea" v-model="formData.product_details.fa.page_description"></el-input>
<p class="err" v-if="validation.fa_page_description">{{validation.fa_page_description.msg}}</p>
</el-form-item>
<h3>بخش دوم صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_more_title1 ? 'is-error' : ''" label="عنوان اول">
<el-input v-model="formData.product_details.fa.more_title1"></el-input>
<p class="err" v-if="validation.fa_more_title1">{{validation.fa_more_title1.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_more_description1 ? 'is-error' : ''" label="توضیح اول">
<el-input type="textarea" v-model="formData.product_details.fa.more_description1"></el-input>
<p class="err" v-if="validation.fa_more_description1">{{validation.fa_more_description1.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_more_title2 ? 'is-error' : ''" label="عنوان دوم">
<el-input v-model="formData.product_details.fa.more_title2"></el-input>
<p class="err" v-if="validation.fa_more_title2">{{validation.fa_more_title2.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_more_description2 ? 'is-error' : ''" label="توضیح دوم">
<el-input type="textarea" v-model="formData.product_details.fa.more_description2"></el-input>
<p class="err" v-if="validation.fa_more_description2">{{validation.fa_more_description2.msg}}</p>
</el-form-item>
<h3>بخش سوم صفحه (جدول و توضیحات)</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_chart_title ? 'is-error' : ''" label="عنوان جدول">
<el-input v-model="formData.product_details.fa.chart_title"></el-input>
<p class="err" v-if="validation.fa_chart_title">{{validation.fa_chart_title.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_chart_description ? 'is-error' : ''" label="توضیحات جدول">
<el-input type="textarea" v-model="formData.product_details.fa.chart_description"></el-input>
<p class="err" v-if="validation.fa_chart_description">{{validation.fa_chart_description.msg}}</p>
</el-form-item>
</el-form>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<el-form>
<h2 style="color: #000;font-weight: bold;font-size: 30px;">انگلیسی</h2>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_name ? 'is-error' : ''" label="نام">
<el-input v-model="formData.product_details.en.name"></el-input>
<p class="err" v-if="validation.en_name">{{validation.en_name.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="formData.product_details.en.short_description"></el-input>
<p class="err" v-if="validation.en_short_description">{{validation.en_short_description.msg}}</p>
</el-form-item>
<h3>بخش اول صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_page_title ? 'is-error' : ''" label="عنوان">
<el-input type="textarea" v-model="formData.product_details.en.page_title"></el-input>
<p class="err" v-if="validation.en_page_title">{{validation.en_page_title.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_page_description ? 'is-error' : ''" label="توضیحات">
<el-input type="textarea" v-model="formData.product_details.en.page_description"></el-input>
<p class="err" v-if="validation.en_page_description">{{validation.en_page_description.msg}}</p>
</el-form-item>
<h3>بخش دوم صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_more_title1 ? 'is-error' : ''" label="عنوان اول">
<el-input v-model="formData.product_details.en.more_title1"></el-input>
<p class="err" v-if="validation.en_more_title1">{{validation.en_more_title1.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_more_description1 ? 'is-error' : ''" label="توضیح اول">
<el-input type="textarea" v-model="formData.product_details.en.more_description1"></el-input>
<p class="err" v-if="validation.en_more_description1">{{validation.en_more_description1.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_more_title2 ? 'is-error' : ''" label="عنوان دوم">
<el-input v-model="formData.product_details.en.more_title2"></el-input>
<p class="err" v-if="validation.en_more_title2">{{validation.en_more_title2.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_more_description2 ? 'is-error' : ''" label="توضیح دوم">
<el-input type="textarea" v-model="formData.product_details.en.more_description2"></el-input>
<p class="err" v-if="validation.en_more_description2">{{validation.en_more_description2.msg}}</p>
</el-form-item>
<h3>بخش سوم صفحه (جدول و توضیحات)</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_chart_title ? 'is-error' : ''" label="عنوان جدول">
<el-input v-model="formData.product_details.en.chart_title"></el-input>
<p class="err" v-if="validation.en_chart_title">{{validation.en_chart_title.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_chart_description ? 'is-error' : ''" label="توضیحات جدول">
<el-input type="textarea" v-model="formData.product_details.en.chart_description"></el-input>
<p class="err" v-if="validation.en_chart_description">{{validation.en_chart_description.msg}}</p>
</el-form-item>
</el-form>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<h2>عکس اول بخش دوم</h2>
<el-divider></el-divider>
<img :src="formData.more_section_image1" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="more_section_image1" @change="previewMore_section_image1">
<p class="err" v-if="validation.more_section_image1">{{validation.more_section_image1.msg}}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 778px عرض و 395px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<h2 class="secondTitle">عکس دوم بخش دوم</h2>
<el-divider></el-divider>
<img :src="formData.more_section_image2" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="more_section_image2" @change="previewMore_section_image2">
<p class="err" v-if="validation.more_section_image2">{{validation.more_section_image2.msg}}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 778px عرض و 395px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<!-- -->
<h2 class="secondTitle">عکس اول شماتیک بخش سوم</h2>
<el-divider></el-divider>
<img :src="formData.render_image1" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="render_image1" @change="previewRender_image1">
<p class="err" v-if="validation.render_image1">{{validation.render_image1.msg}}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 300px عرض و 300px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<el-form>
<el-form-item prop="title" :class="validation.fa_render_caption1 ? 'is-error' : ''" label="کپشن فارسی">
<el-input v-model="formData.product_details.fa.render_caption1"></el-input>
<p class="err" v-if="validation.fa_render_caption1">{{validation.fa_render_caption1.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_render_caption1 ? 'is-error' : ''" label="کپشن انگلیسی">
<el-input v-model="formData.product_details.en.render_caption1"></el-input>
<p class="err" v-if="validation.en_render_caption1">{{validation.en_render_caption1.msg}}</p>
</el-form-item>
</el-form>
<!-- -->
<h2 class="secondTitle">عکس دوم شماتیک بخش سوم</h2>
<el-divider></el-divider>
<img :src="formData.render_image2" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="render_image2" @change="previewRender_image2">
<p class="err" v-if="validation.render_image2">{{validation.render_image2.msg}}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 300px عرض و 300px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<el-form>
<el-form-item prop="title" :class="validation.fa_render_caption2 ? 'is-error' : ''" label="کپشن فارسی">
<el-input v-model="formData.product_details.fa.render_caption2"></el-input>
<p class="err" v-if="validation.fa_render_caption2">{{validation.fa_render_caption2.msg}}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_render_caption2 ? 'is-error' : ''" label="کپشن انگلیسی">
<el-input v-model="formData.product_details.en.render_caption2"></el-input>
<p class="err" v-if="validation.en_render_caption2">{{validation.en_render_caption2.msg}}</p>
</el-form-item>
</el-form>
<!-- -->
<h2 class="secondTitle">عکس جدول مشخصات محصول</h2>
<el-divider></el-divider>
<img :src="formData.chart_image" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="chart_image" @change="previewChart_image">
<p class="err" v-if="validation.chart_image">{{validation.chart_image.msg}}</p>
</admin-panel>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<admin-title-bar :title="title">
<el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button>
<el-button type="success" @click="upload">ایجاد</el-button>
</admin-title-bar>
<div class="col-6">
<admin-panel>
<p style="margin-bottom: 50px;color: green;font-weight: bold;font-size: 20px;">ابتدا محصول را ثبت کرده، سپس در مرحله بعد عکس های بیشتر و ویژگی های محصول را وارد کنید.</p>
<el-form>
<el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی">
<el-select v-model="formData.category" placeholder="انتخاب کنید">
<el-option
v-for="item in productCategories"
:key="item._id"
:label="item.category_details.fa.name"
:value="item._id">
</el-option>
</el-select>
<p class="err" v-if="validation.category">{{ validation.category.msg }}</p>
</el-form-item>
<el-form-item prop="published" label="بخش دوم نمایش داده شود">
<el-switch v-model="formData.more_section" style="margin-right: 15px;"></el-switch>
</el-form-item>
<el-form-item prop="published" label="دارای فایل های قابل دانلود باشد">
<el-switch v-model="formData.download_section" style="margin-right: 15px;"></el-switch>
</el-form-item>
<el-form-item prop="published" label="در صفحه اصلی باشد">
<el-switch v-model="formData.favorite" style="margin-right: 15px;"></el-switch>
</el-form-item>
</el-form>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<h2>کاور</h2>
<el-divider></el-divider>
<img :src="formData.cover" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="cover" @change="previewCover">
<p class="err" v-if="validation.cover">{{ validation.cover.msg }}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 1010px عرض و 534px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<el-form>
<h2 style="color: #000;font-weight: bold;font-size: 30px;">فارسی</h2>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_name ? 'is-error' : ''" label="نام">
<el-input v-model="formData.product_details.fa.name"></el-input>
<p class="err" v-if="validation.fa_name">{{ validation.fa_name.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="formData.product_details.fa.short_description"></el-input>
<p class="err" v-if="validation.fa_short_description">{{ validation.fa_short_description.msg }}</p>
</el-form-item>
<h3>بخش اول صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_page_title ? 'is-error' : ''" label="عنوان">
<el-input type="textarea" v-model="formData.product_details.fa.page_title"></el-input>
<p class="err" v-if="validation.fa_page_title">{{ validation.fa_page_title.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_page_description ? 'is-error' : ''" label="توضیحات">
<el-input type="textarea" v-model="formData.product_details.fa.page_description"></el-input>
<p class="err" v-if="validation.fa_page_description">{{ validation.fa_page_description.msg }}</p>
</el-form-item>
<h3>بخش دوم صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_more_title1 ? 'is-error' : ''" label="عنوان اول">
<el-input v-model="formData.product_details.fa.more_title1"></el-input>
<p class="err" v-if="validation.fa_more_title1">{{ validation.fa_more_title1.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_more_description1 ? 'is-error' : ''" label="توضیح اول">
<el-input type="textarea" v-model="formData.product_details.fa.more_description1"></el-input>
<p class="err" v-if="validation.fa_more_description1">{{ validation.fa_more_description1.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_more_title2 ? 'is-error' : ''" label="عنوان دوم">
<el-input v-model="formData.product_details.fa.more_title2"></el-input>
<p class="err" v-if="validation.fa_more_title2">{{ validation.fa_more_title2.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_more_description2 ? 'is-error' : ''" label="توضیح دوم">
<el-input type="textarea" v-model="formData.product_details.fa.more_description2"></el-input>
<p class="err" v-if="validation.fa_more_description2">{{ validation.fa_more_description2.msg }}</p>
</el-form-item>
<h3>بخش سوم صفحه (جدول و توضیحات)</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_chart_title ? 'is-error' : ''" label="عنوان جدول">
<el-input v-model="formData.product_details.fa.chart_title"></el-input>
<p class="err" v-if="validation.fa_chart_title">{{ validation.fa_chart_title.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.fa_chart_description ? 'is-error' : ''" label="توضیحات جدول">
<el-input type="textarea" v-model="formData.product_details.fa.chart_description"></el-input>
<p class="err" v-if="validation.fa_chart_description">{{ validation.fa_chart_description.msg }}</p>
</el-form-item>
</el-form>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<el-form>
<h2 style="color: #000;font-weight: bold;font-size: 30px;">انگلیسی</h2>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_name ? 'is-error' : ''" label="نام">
<el-input v-model="formData.product_details.en.name"></el-input>
<p class="err" v-if="validation.en_name">{{ validation.en_name.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_short_description ? 'is-error' : ''" label="توضیح کوتاه">
<el-input type="textarea" v-model="formData.product_details.en.short_description"></el-input>
<p class="err" v-if="validation.en_short_description">{{ validation.en_short_description.msg }}</p>
</el-form-item>
<h3>بخش اول صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_page_title ? 'is-error' : ''" label="عنوان">
<el-input type="textarea" v-model="formData.product_details.en.page_title"></el-input>
<p class="err" v-if="validation.en_page_title">{{ validation.en_page_title.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_page_description ? 'is-error' : ''" label="توضیحات">
<el-input type="textarea" v-model="formData.product_details.en.page_description"></el-input>
<p class="err" v-if="validation.en_page_description">{{ validation.en_page_description.msg }}</p>
</el-form-item>
<h3>بخش دوم صفحه</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_more_title1 ? 'is-error' : ''" label="عنوان اول">
<el-input v-model="formData.product_details.en.more_title1"></el-input>
<p class="err" v-if="validation.en_more_title1">{{ validation.en_more_title1.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_more_description1 ? 'is-error' : ''" label="توضیح اول">
<el-input type="textarea" v-model="formData.product_details.en.more_description1"></el-input>
<p class="err" v-if="validation.en_more_description1">{{ validation.en_more_description1.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_more_title2 ? 'is-error' : ''" label="عنوان دوم">
<el-input v-model="formData.product_details.en.more_title2"></el-input>
<p class="err" v-if="validation.en_more_title2">{{ validation.en_more_title2.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_more_description2 ? 'is-error' : ''" label="توضیح دوم">
<el-input type="textarea" v-model="formData.product_details.en.more_description2"></el-input>
<p class="err" v-if="validation.en_more_description2">{{ validation.en_more_description2.msg }}</p>
</el-form-item>
<h3>بخش سوم صفحه (جدول و توضیحات)</h3>
<el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_chart_title ? 'is-error' : ''" label="عنوان جدول">
<el-input v-model="formData.product_details.en.chart_title"></el-input>
<p class="err" v-if="validation.en_chart_title">{{ validation.en_chart_title.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_chart_description ? 'is-error' : ''" label="توضیحات جدول">
<el-input type="textarea" v-model="formData.product_details.en.chart_description"></el-input>
<p class="err" v-if="validation.en_chart_description">{{ validation.en_chart_description.msg }}</p>
</el-form-item>
</el-form>
</admin-panel>
</div>
<div class="col-6">
<admin-panel>
<h2>عکس اول بخش دوم</h2>
<el-divider></el-divider>
<img :src="formData.more_section_image1" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="more_section_image1" @change="previewMore_section_image1">
<p class="err" v-if="validation.more_section_image1">{{ validation.more_section_image1.msg }}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 778px عرض و 395px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<h2 class="secondTitle">عکس دوم بخش دوم</h2>
<el-divider></el-divider>
<img :src="formData.more_section_image2" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="more_section_image2" @change="previewMore_section_image2">
<p class="err" v-if="validation.more_section_image2">{{ validation.more_section_image2.msg }}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 778px عرض و 395px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<!-- -->
<h2 class="secondTitle">عکس اول شماتیک بخش سوم</h2>
<el-divider></el-divider>
<img :src="formData.render_image1" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="render_image1" @change="previewRender_image1">
<p class="err" v-if="validation.render_image1">{{ validation.render_image1.msg }}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 300px عرض و 300px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<el-form>
<el-form-item prop="title" :class="validation.fa_render_caption1 ? 'is-error' : ''" label="کپشن فارسی">
<el-input v-model="formData.product_details.fa.render_caption1"></el-input>
<p class="err" v-if="validation.fa_render_caption1">{{ validation.fa_render_caption1.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_render_caption1 ? 'is-error' : ''" label="کپشن انگلیسی">
<el-input v-model="formData.product_details.en.render_caption1"></el-input>
<p class="err" v-if="validation.en_render_caption1">{{ validation.en_render_caption1.msg }}</p>
</el-form-item>
</el-form>
<!-- -->
<h2 class="secondTitle">عکس دوم شماتیک بخش سوم</h2>
<el-divider></el-divider>
<img :src="formData.render_image2" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="render_image2" @change="previewRender_image2">
<p class="err" v-if="validation.render_image2">{{ validation.render_image2.msg }}</p>
<p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 300px عرض و 300px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<el-form>
<el-form-item prop="title" :class="validation.fa_render_caption2 ? 'is-error' : ''" label="کپشن فارسی">
<el-input v-model="formData.product_details.fa.render_caption2"></el-input>
<p class="err" v-if="validation.fa_render_caption2">{{ validation.fa_render_caption2.msg }}</p>
</el-form-item>
<el-form-item prop="title" :class="validation.en_render_caption2 ? 'is-error' : ''" label="کپشن انگلیسی">
<el-input v-model="formData.product_details.en.render_caption2"></el-input>
<p class="err" v-if="validation.en_render_caption2">{{ validation.en_render_caption2.msg }}</p>
</el-form-item>
</el-form>
<!-- -->
<h2 class="secondTitle">عکس جدول مشخصات محصول</h2>
<el-divider></el-divider>
<img :src="formData.chart_image" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="chart_image" @change="previewChart_image">
<p class="err" v-if="validation.chart_image">{{ validation.chart_image.msg }}</p>
</admin-panel>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
formData: {
cover: '',
more_section_image1: '',
more_section_image2: '',
render_image1: '',
render_image2: '',
chart_image: '',
category: '',
more_section: true,
download_section: true,
product_details: {
fa: {
name: '',
short_description: '',
page_title: '',
page_description: '',
more_title1: '',
more_description1: '',
more_title2: '',
more_description2: '',
render_caption1: '',
render_caption2: '',
chart_title: '',
chart_description: ''
},
en: {
name: '',
short_description: '',
page_title: '',
page_description: '',
more_title1: '',
more_description1: '',
more_title2: '',
more_description2: '',
render_caption1: '',
render_caption2: '',
chart_title: '',
chart_description: ''
}
}
},
productCategories: null,
validation: {},
uploading: false,
uploadProgress: null
}
export default {
data() {
return {
formData: {
cover: '',
more_section_image1: '',
more_section_image2: '',
render_image1: '',
render_image2: '',
chart_image: '',
category: '',
more_section: true,
download_section: true,
favorite: false,
product_details: {
fa: {
name: '',
short_description: '',
page_title: '',
page_description: '',
more_title1: '',
more_description1: '',
more_title2: '',
more_description2: '',
render_caption1: '',
render_caption2: '',
chart_title: '',
chart_description: ''
},
en: {
name: '',
short_description: '',
page_title: '',
page_description: '',
more_title1: '',
more_description1: '',
more_title2: '',
more_description2: '',
render_caption1: '',
render_caption2: '',
chart_title: '',
chart_description: ''
}
}
},
computed: {
title() {
if (!this.uploading) {
return 'افزودن محصول'
} else {
return this.uploadProgress
}
}
},
watch: {
async locale(newVal, oldVal) {
let productCategories = await this.$axios.get(`/api/public/productCategories/${newVal}`)
this.productCategories = productCategories.data
}
},
methods: {
upload() {
this.validation = ''
const data = new FormData();
data.append('fa_name', this.formData.product_details.fa.name)
data.append('fa_short_description', this.formData.product_details.fa.short_description)
data.append('fa_page_title', this.formData.product_details.fa.page_title)
data.append('fa_page_description', this.formData.product_details.fa.page_description)
data.append('fa_more_title1', this.formData.product_details.fa.more_title1)
data.append('fa_more_description1', this.formData.product_details.fa.more_description1)
data.append('fa_more_title2', this.formData.product_details.fa.more_title2)
data.append('fa_more_description2', this.formData.product_details.fa.more_description2)
data.append('fa_render_caption1', this.formData.product_details.fa.render_caption1)
data.append('fa_render_caption2', this.formData.product_details.fa.render_caption2)
data.append('fa_chart_title', this.formData.product_details.fa.chart_title)
data.append('fa_chart_description', this.formData.product_details.fa.chart_description)
data.append('en_name', this.formData.product_details.en.name)
data.append('en_short_description', this.formData.product_details.en.short_description)
data.append('en_page_title', this.formData.product_details.en.page_title)
data.append('en_page_description', this.formData.product_details.en.page_description)
data.append('en_more_title1', this.formData.product_details.en.more_title1)
data.append('en_more_description1', this.formData.product_details.en.more_description1)
data.append('en_more_title2', this.formData.product_details.en.more_title2)
data.append('en_more_description2', this.formData.product_details.en.more_description2)
data.append('en_render_caption1', this.formData.product_details.en.render_caption1)
data.append('en_render_caption2', this.formData.product_details.en.render_caption2)
data.append('en_chart_title', this.formData.product_details.en.chart_title)
data.append('en_chart_description', this.formData.product_details.en.chart_description)
data.append('category', this.formData.category)
data.append('download_section', this.formData.download_section)
data.append('more_section', this.formData.more_section)
data.append('cover', this.$refs.cover.files[0])
data.append('more_section_image1', this.$refs.more_section_image1.files[0])
data.append('more_section_image2', this.$refs.more_section_image2.files[0])
data.append('render_image1', this.$refs.render_image1.files[0])
data.append('render_image2', this.$refs.render_image2.files[0])
data.append('chart_image', this.$refs.chart_image.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor(((progressEvent.loaded / progressEvent.total) * 100)) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios.post(`/api/private/products`, data, axiosConfig)
.then(response => {
if (response.data) {
this.$message({
message: 'محصول با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push(`/admin/products/${response.data._id}`)
}
}).catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه',
})
}
})
},
previewCover(event) {
this.formData.cover = URL.createObjectURL(event.target.files[0]);
},
previewMore_section_image1(event) {
this.formData.more_section_image1 = URL.createObjectURL(event.target.files[0]);
},
previewMore_section_image2(event) {
this.formData.more_section_image2 = URL.createObjectURL(event.target.files[0]);
},
previewRender_image1(event) {
this.formData.render_image1 = URL.createObjectURL(event.target.files[0]);
},
previewRender_image2(event) {
this.formData.render_image1 = URL.createObjectURL(event.target.files[0]);
},
previewChart_image(event) {
this.formData.chart_image = URL.createObjectURL(event.target.files[0]);
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, store}) {
let productCategories = await $axios.get(`/api/public/productCategories`)
return {
productCategories: productCategories.data
}
productCategories: null,
validation: {},
uploading: false,
uploadProgress: null
}
},
computed: {
title() {
if (!this.uploading) {
return 'افزودن محصول'
} else {
return this.uploadProgress
}
}
}
},
watch: {
async locale(newVal, oldVal) {
let productCategories = await this.$axios.get(`/api/public/productCategories/${newVal}`)
this.productCategories = productCategories.data
}
},
methods: {
upload() {
this.validation = ''
const data = new FormData();
data.append('fa_name', this.formData.product_details.fa.name)
data.append('fa_short_description', this.formData.product_details.fa.short_description)
data.append('fa_page_title', this.formData.product_details.fa.page_title)
data.append('fa_page_description', this.formData.product_details.fa.page_description)
data.append('fa_more_title1', this.formData.product_details.fa.more_title1)
data.append('fa_more_description1', this.formData.product_details.fa.more_description1)
data.append('fa_more_title2', this.formData.product_details.fa.more_title2)
data.append('fa_more_description2', this.formData.product_details.fa.more_description2)
data.append('fa_render_caption1', this.formData.product_details.fa.render_caption1)
data.append('fa_render_caption2', this.formData.product_details.fa.render_caption2)
data.append('fa_chart_title', this.formData.product_details.fa.chart_title)
data.append('fa_chart_description', this.formData.product_details.fa.chart_description)
data.append('en_name', this.formData.product_details.en.name)
data.append('en_short_description', this.formData.product_details.en.short_description)
data.append('en_page_title', this.formData.product_details.en.page_title)
data.append('en_page_description', this.formData.product_details.en.page_description)
data.append('en_more_title1', this.formData.product_details.en.more_title1)
data.append('en_more_description1', this.formData.product_details.en.more_description1)
data.append('en_more_title2', this.formData.product_details.en.more_title2)
data.append('en_more_description2', this.formData.product_details.en.more_description2)
data.append('en_render_caption1', this.formData.product_details.en.render_caption1)
data.append('en_render_caption2', this.formData.product_details.en.render_caption2)
data.append('en_chart_title', this.formData.product_details.en.chart_title)
data.append('en_chart_description', this.formData.product_details.en.chart_description)
data.append('category', this.formData.category)
data.append('download_section', this.formData.download_section)
data.append('more_section', this.formData.more_section)
data.append('favorite', this.formData.favorite)
data.append('cover', this.$refs.cover.files[0])
data.append('more_section_image1', this.$refs.more_section_image1.files[0])
data.append('more_section_image2', this.$refs.more_section_image2.files[0])
data.append('render_image1', this.$refs.render_image1.files[0])
data.append('render_image2', this.$refs.render_image2.files[0])
data.append('chart_image', this.$refs.chart_image.files[0])
const axiosConfig = {
onUploadProgress: progressEvent => {
this.uploading = true
this.uploadProgress = 'درحال آپلود ' + Math.floor(((progressEvent.loaded / progressEvent.total) * 100)) + '%'
if ((progressEvent.loaded / progressEvent.total) * 100 === 100) {
this.uploading = false
}
}
}
this.$axios.post(`/api/private/products`, data, axiosConfig)
.then(response => {
if (response.data) {
this.$message({
message: 'محصول با موفقیت ثبت شد.',
type: 'success'
})
this.$router.push(`/admin/products/${response.data._id}`)
}
}).catch(error => {
if (error.response.status === 422) {
this.validation = error.response.data.validation
this.$message({
type: 'error',
message: 'اطلاعات رو بررسی و دوباره تلاش کنید'
})
} else {
this.$alert(error.response.data.message, 'خطا', {
confirmButtonText: 'باشه',
})
}
})
},
previewCover(event) {
this.formData.cover = URL.createObjectURL(event.target.files[0]);
},
previewMore_section_image1(event) {
this.formData.more_section_image1 = URL.createObjectURL(event.target.files[0]);
},
previewMore_section_image2(event) {
this.formData.more_section_image2 = URL.createObjectURL(event.target.files[0]);
},
previewRender_image1(event) {
this.formData.render_image1 = URL.createObjectURL(event.target.files[0]);
},
previewRender_image2(event) {
this.formData.render_image2 = URL.createObjectURL(event.target.files[0]);
},
previewChart_image(event) {
this.formData.chart_image = URL.createObjectURL(event.target.files[0]);
}
},
head() {
return {
title: this.title
}
},
layout: 'admin',
async asyncData({$axios, store}) {
let productCategories = await $axios.get(`/api/public/productCategories`)
return {
productCategories: productCategories.data
}
}
}
</script>
+18 -1
View File
@@ -1,3 +1,20 @@
export const state = () => ({})
export const state = () => ({
email: 'info@arakrail.com',
tell: '+988634132704',
tell_view: '+98 86 3 413 2704 - 7',
fax: '+988634132703',
fax_view: '+98 86 3 413 27 03',
address: {
fa: 'استان مرکزی، اراک، شهرک قطب صنعتی، خیابان تلاش، همت 6، توسعه 3',
en: 'No.3 Tose-e St., No.6 Hemmat St., Industrial Pole District, Arak City, Markazi Province, Iran'
},
instagram_url: 'https://instagram.com/arakrail_grating',
linkedin_url: 'https://www.linkedin.com/in/arak-rail-co-27040937',
meta_description: {
fa: 'شرکت اراک ریل در تاریخ ۱۳۷۰/۰۳/۲۹ با هدف تولید بخشی از قطعات و مجموعه های وارداتی مورد مصرف در صنایع ایران به خصوص راه آهن ، با مجوز وزارت صنایع ، تاسیس و در مساحت حدود ۶۰۰۰ متر مربع و با بیش از ۱۵۰۰ متر مربع کارگاه با مجموعه ای از امکانات ماشین کاری ، برش کاری ، پرس کاری و جوش کاری راه اندازی شد .شرکت اراک ریل مفتخر است که از سال ۱۳۸۵ برای اولین بار در کشور ...',
en: 'Arak Rail Company was established on 1370/03/29 with the aim of producing a part of imported parts and assemblies used in Iranian industries, especially railways, with the permission of the Ministry of Industry, in an area of about 6000 square meters and with more than 1500 square meters. The workshop was set up with a set of machining, cutting, pressing and welding facilities. Arak Rail Company is proud to be the first in the country since 2006 ...'
},
calc_app_link: ''
})
export const mutations = {}
+870 -670
View File
File diff suppressed because it is too large Load Diff