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') const v_m = require('../validation_messages')
module.exports.create = [ module.exports.create = [
[ [
body('fa_name') body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title) .notEmpty().withMessage(v_m['fa'].required.title)
.bail() .bail()
.custom((value, {req}) => { .custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => { return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => {
if (category) return Promise.reject(v_m['fa'].duplicated.title) if (category) return Promise.reject(v_m['fa'].duplicated.title)
return true 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
})
}) })
], }),
(req, res) => { body('en_name')
const errors = validationResult(req) .notEmpty().withMessage(v_m['fa'].required.title)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) .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({ const blogCategory = new BlogCategory({
blogCategory_details: { blogCategory_details: {
fa: { fa: {
name: req.body.fa_name name: req.body.fa_name
}, },
en: { en: {
name: req.body.en_name name: req.body.en_name
} }
}, },
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}) })
blogCategory.save(err => { blogCategory.save(err => {
if (err) console.log(err) if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save}) return res.json({message: v_m['fa'].response.success_save})
}) })
} }
] ]
module.exports.getAll = [ module.exports.getAll = [
(req, res) => { (req, res) => {
BlogCategory.find({}, (err, categories) => { BlogCategory.find({}, (err, categories) => {
if (err) return res.status(500).json({message: err}) if (err) return res.status(500).json({message: err})
return res.json(categories) return res.json(categories)
}) })
} }
] ]
module.exports.getOne = [ module.exports.getOne = [
(req, res) => { (req, res) => {
BlogCategory.findById(req.params.id, (err, category) => { BlogCategory.findById(req.params.id, (err, category) => {
if (err) return res.status(404).json({message: err}) if (err) return res.status(404).json({message: err})
return res.json(category) return res.json(category)
}) })
} }
] ]
module.exports.update = [ module.exports.update = [
[ [
body('fa_name') body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title) .notEmpty().withMessage(v_m['fa'].required.title)
.bail() .bail()
.custom((value, {req}) => { .custom((value, {req}) => {
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => { 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) if (category && category._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true 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
})
}) })
], }),
(req, res) => { body('en_name')
const errors = validationResult(req) .notEmpty().withMessage(v_m['fa'].required.title)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) .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 = { const data = {
blogCategory_details: { blogCategory_details: {
fa: { fa: {
name: req.body.fa_name name: req.body.fa_name
}, },
en: { en: {
name: req.body.en_name name: req.body.en_name
} }
}, },
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
} }
BlogCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => { BlogCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) console.log(err) if (err) console.log(err)
return res.json({message: v_m['fa'].response.success_save}) return res.json({message: v_m['fa'].response.success_save})
}) })
} }
] ]
module.exports.delete = [ module.exports.delete = [
(req, res) => { (req, res) => {
BlogPost.find({category: req.params.id}, (err, posts) => { BlogPost.find({category: req.params.id}, (err, posts) => {
if (err) console.log(err) if (err) console.log(err)
if (!posts.length) { if (!posts.length) {
BlogCategory.findByIdAndDelete(req.params.id, (err) => { BlogCategory.findByIdAndDelete(req.params.id, (err) => {
if (err) return res.status(404).json({message: err}) if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_save}) return res.json({message: v_m['fa'].response.success_save})
}) })
} else { } else {
return res.status(500).json({message: 'نمیتوان دسته بندی هایی که دارای پست هستند را پاک کرد.'}) return res.status(500).json({message: 'نمیتوان دسته بندی هایی که دارای پست هستند را پاک کرد.'})
} }
}) })
} }
] ]
+212 -212
View File
@@ -5,246 +5,246 @@ const fs = require('fs')
const jimp = require('jimp') const jimp = require('jimp')
const v_m = require('../validation_messages') 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 = [ module.exports.create = [
[ [
// title // title
body('fa_title') body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title) .notEmpty().withMessage(v_m['fa'].required.title)
.bail() .bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120) .isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail() .bail()
.custom((value, {req}) => { .custom((value, {req}) => {
return BlogPost.findOne({'post_details.fa.title': value}).then(post => { return BlogPost.findOne({'post_details.fa.title': value}).then(post => {
if (post) return Promise.reject(v_m['fa'].duplicated.title) if (post) return Promise.reject(v_m['fa'].duplicated.title)
return true 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}`)
}) })
}),
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 = { // description
post_details: { body('fa_description')
fa: { .notEmpty().withMessage(v_m['fa'].required.description),
title: req.body.fa_title, body('en_description')
description: req.body.fa_description, .notEmpty().withMessage(v_m['fa'].required.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')
}
const post = new BlogPost(data) // short description
post.save(err => { body('fa_short_description')
if (err) console.log(err) .notEmpty().withMessage(v_m['fa'].required.description),
return res.json({message: v_m['fa'].response.success_save}) 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 = [ module.exports.getAll = [
(req, res) => { (req, res) => {
BlogPost.find({}).sort({_id: -1}).exec((err, posts) => { BlogPost.find({}).sort({_id: -1}).exec((err, posts) => {
if (err) console.log(err) if (err) console.log(err)
return res.json(posts) return res.json(posts)
}) })
} }
] ]
module.exports.getOne = [ module.exports.getOne = [
(req, res) => { (req, res) => {
BlogPost.findById(req.params.id, (err, post) => { BlogPost.findById(req.params.id, (err, post) => {
if (err) console.log(err) if (err) console.log(err)
return res.json(post) return res.json(post)
}) })
} }
] ]
module.exports.update = [ module.exports.update = [
[ [
// title // title
body('fa_title') body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title) .notEmpty().withMessage(v_m['fa'].required.title)
.bail() .bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120) .isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail() .bail()
.custom((value, {req}) => { .custom((value, {req}) => {
return BlogPost.findOne({'post_details.fa.title': value}).then(post => { 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) if (post && post._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true return true
}) })
}), }),
body('en_title') body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title) .notEmpty().withMessage(v_m['fa'].required.title)
.bail() .bail()
.isLength({max: 120}).withMessage(v_m['fa'].max_char.max120) .isLength({max: 120}).withMessage(v_m['fa'].max_char.max120)
.bail() .bail()
.custom((value, {req}) => { .custom((value, {req}) => {
return BlogPost.findOne({'post_details.en.title': value}).then(post => { 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) if (post && post._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.title)
return true return true
}) })
}), }),
// description // description
body('fa_description') body('fa_description')
.notEmpty().withMessage(v_m['fa'].required.description), .notEmpty().withMessage(v_m['fa'].required.description),
body('en_description') body('en_description')
.notEmpty().withMessage(v_m['fa'].required.description), .notEmpty().withMessage(v_m['fa'].required.description),
// short description // short description
body('fa_short_description') body('fa_short_description')
.notEmpty().withMessage(v_m['fa'].required.description) .notEmpty().withMessage(v_m['fa'].required.description),
.bail() body('en_short_description')
.isLength({max: 200}).withMessage(v_m['fa'].max_char.max200), .notEmpty().withMessage(v_m['fa'].required.description),
body('en_short_description')
.notEmpty().withMessage(v_m['fa'].required.description)
.bail()
.isLength({max: 200}).withMessage(v_m['fa'].max_char.max200),
body('category') body('category')
.notEmpty().withMessage(v_m['fa'].required.category) .notEmpty().withMessage(v_m['fa'].required.category)
], ],
(req, res) => { (req, res) => {
const errors = validationResult(req) const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = { const data = {
post_details: { post_details: {
fa: { fa: {
title: req.body.fa_title, title: req.body.fa_title,
description: req.body.fa_description, description: req.body.fa_description,
short_description: req.body.fa_short_description short_description: req.body.fa_short_description.slice(0, shortDescriptionLength) + ' ... '
}, },
en: { en: {
title: req.body.en_title, title: req.body.en_title,
description: req.body.en_description, description: req.body.en_description,
short_description: req.body.en_short_description short_description: req.body.en_short_description.slice(0, shortDescriptionLength) + ' ... '
} }
}, },
published: req.body.published, published: req.body.published,
category: req.body.category, category: req.body.category,
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') 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)
})
} }
BlogPost.findById(oldData._id, (err, newData) => {
// 460 X 320 if (err) console.log(err)
// 1920 x 720 return res.json(newData)
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})
}) })
} })
}
] ]
module.exports.delete = [ module.exports.delete = [
(req, res) => { (req, res) => {
BlogPost.findByIdAndDelete(req.params.id, (err, post) => { BlogPost.findByIdAndDelete(req.params.id, (err, post) => {
if (err) return res.status(404).json({message: err}) if (err) return res.status(404).json({message: err})
fs.unlink(`./static/${post.cover}`, err => { fs.unlink(`./static/${post.cover}`, err => {
if (err) console.log(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})
}) })
} 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 v_m = require('../validation_messages')
const validationMessages = { const validationMessages = {
fa: {}, fa: {
en: {} 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 = [ const values = {
[ // ArakRail products
body('method') bearingBarPitch_forge: [30, 35, 41, 50],
.notEmpty().withMessage(), bearingBarPitch_pressured: [11, 22, 33, 44, 50, 55],
body('type') // defined in formula
.notEmpty().withMessage(), crossBarPitch_forge: [38, 50, 76, 100],
body('class') crossBarPitch_pressured: [11, 22, 33, 44, 50, 55, 66, 77, 88, 100],
.notEmpty().withMessage(), // defined in formula
body('pointLoad') bearingBarHeight: [20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
.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) => {
} 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 fs = require('fs')
const v_m = require('../validation_messages') const v_m = require('../validation_messages')
// local variables
const imageWidth = 648
const imageHeight = 443
const imageQuality = 100
module.exports.create = [ module.exports.create = [
[ [
body('fa_title') body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title), .notEmpty().withMessage(v_m['fa'].required.title),
body('en_title') body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title), .notEmpty().withMessage(v_m['fa'].required.title),
body('year') body('year')
.notEmpty().withMessage(v_m['fa'].required.date) .notEmpty().withMessage(v_m['fa'].required.date)
.bail() .bail()
.isNumeric().withMessage(v_m['fa'].format.number) .isNumeric().withMessage(v_m['fa'].format.number)
.bail() .bail()
.isLength({min: 4}).withMessage(v_m['fa'].min_char.min4) .isLength({min: 4}).withMessage(v_m['fa'].min_char.min4)
.bail() .bail()
.isLength({max: 4}).withMessage(v_m['fa'].max_char.max4) .isLength({max: 4}).withMessage(v_m['fa'].max_char.max4)
], ],
(req, res) => { (req, res) => {
const errors = validationResult(req) const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) 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}}}) 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 = { const data = {
image: fileName, image: fileName,
year: Number(req.body.year), year: Number(req.body.year),
history_details: { history_details: {
fa: { fa: {
title: req.body.fa_title, title: req.body.fa_title,
caption: req.body.fa_caption caption: req.body.fa_caption
}, },
en: { en: {
title: req.body.en_title, title: req.body.en_title,
caption: req.body.en_caption caption: req.body.en_caption
} }
}, },
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
} }
jimp.read(req.files.image.data) jimp.read(req.files.image.data)
.then(img => { .then(img => {
img img
.resize(380, jimp.AUTO) .resize(imageWidth, jimp.AUTO)
.cover(380, 260) .cover(imageWidth, imageHeight)
.write(`./static/uploads/images/history/${fileName}`, cb => { .quality(imageQuality)
const history = new History(data) .write(`./static/uploads/images/history/${fileName}`, cb => {
history.save(err => { const history = new History(data)
if (err) console.log(err) history.save(err => {
return res.json(v_m['fa'].response.success_save) if (err) console.log(err)
}) return res.json(v_m['fa'].response.success_save)
}) })
}) })
.catch(err => { })
console.log(err) .catch(err => {
}) console.log(err)
} })
}
] ]
module.exports.getAll = [ module.exports.getAll = [
(req, res) => { (req, res) => {
History.find({}).sort({year: 1}).exec((err, data) => { History.find({}).sort({year: 1}).exec((err, data) => {
if (err) console.log(err) if (err) console.log(err)
return res.json(data) return res.json(data)
}) })
} }
] ]
module.exports.getOne = [ module.exports.getOne = [
(req, res) => { (req, res) => {
History.findById(req.params.id, (err, data) => { History.findById(req.params.id, (err, data) => {
if (err) return res.status(404).json(err) if (err) return res.status(404).json(err)
return res.json(data) return res.json(data)
}) })
} }
] ]
module.exports.update = [ module.exports.update = [
[ [
body('fa_title') body('fa_title')
.notEmpty().withMessage(v_m['fa'].required.title), .notEmpty().withMessage(v_m['fa'].required.title),
body('en_title') body('en_title')
.notEmpty().withMessage(v_m['fa'].required.title), .notEmpty().withMessage(v_m['fa'].required.title),
body('year') body('year')
.notEmpty().withMessage(v_m['fa'].required.date) .notEmpty().withMessage(v_m['fa'].required.date)
.bail() .bail()
.isNumeric().withMessage(v_m['fa'].format.number) .isNumeric().withMessage(v_m['fa'].format.number)
.bail() .bail()
.isLength({min: 4}).withMessage(v_m['fa'].min_char.min4) .isLength({min: 4}).withMessage(v_m['fa'].min_char.min4)
.bail() .bail()
.isLength({max: 4}).withMessage(v_m['fa'].max_char.max4) .isLength({max: 4}).withMessage(v_m['fa'].max_char.max4)
], ],
(req, res) => { (req, res) => {
const errors = validationResult(req) const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = { const data = {
year: Number(req.body.year), year: Number(req.body.year),
history_details: { history_details: {
fa: { fa: {
title: req.body.fa_title, title: req.body.fa_title,
caption: req.body.fa_caption caption: req.body.fa_caption
}, },
en: { en: {
title: req.body.en_title, title: req.body.en_title,
caption: req.body.en_caption caption: req.body.en_caption
} }
}, },
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
} }
if (req.files && req.files.image) { if (req.files && req.files.image) {
let fileName = 'history_' + Date.now() + '.' + req.files.image.mimetype.split('/')[1] let fileName = 'history_' + Date.now() + '.' + req.files.image.mimetype.split('/')[1]
data.image = fileName data.image = fileName
jimp.read(req.files.image.data) jimp.read(req.files.image.data)
.then(img => { .then(img => {
img img
.resize(380, jimp.AUTO) .resize(imageWidth, jimp.AUTO)
.cover(380, 260) .cover(imageWidth, imageHeight)
.write(`./static/uploads/images/history/${fileName}`, cb => { .quality(imageQuality)
History.findByIdAndUpdate(req.params.id, data, (err, oldData) => { .write(`./static/uploads/images/history/${fileName}`, cb => {
if (err) console.log(err) History.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
fs.unlink(`./static/${oldData.image}`, err => { if (err) console.log(err)
if (err) console.log(err) fs.unlink(`./static/${oldData.image}`, err => {
return res.json(v_m['fa'].response.success_save) 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 = [ module.exports.delete = [
(req, res) => { (req, res) => {
History.findByIdAndDelete(req.params.id, (err, data) => { History.findByIdAndDelete(req.params.id, (err, data) => {
if (err) console.log(err) if (err) console.log(err)
fs.unlink(`./static/${data.image}`, err => { fs.unlink(`./static/${data.image}`, err => {
if (err) console.log(err) if (err) console.log(err)
return res.json(v_m['fa'].response.success_remove) 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') const fs = require('fs')
module.exports.create = [ module.exports.create = [
(req, res) => { (req, res) => {
if (!req.files || !req.files.pdf) return res.status(422).json({validation: {pdf: {msg: v_m['fa'].required.file}}}) 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}}}) 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) => { MainCatalog.find({}, (err, catalogs) => {
if (catalogs.length) { if (catalogs.length) {
let firstFile = catalogs[0] 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)
})
}) if (firstFile.file[req.body.locale]) fs.unlink(`./static/${firstFile.file[req.body.locale]}`, err => {
} else { if (err) console.log(err)
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)
})
}
})
} 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 = [ module.exports.get = [
(req, res) => { (req, res) => {
MainCatalog.find({}, (err, catalog) => { MainCatalog.find({}, (err, catalog) => {
if (err) console.log(err) if (err) console.log(err)
if (catalog.length) return res.json(catalog[0]) if (catalog.length) return res.json(catalog[0])
else return res.json({}) else return res.json({})
}) })
} }
] ]
+76 -75
View File
@@ -5,101 +5,102 @@ const dateformat = require('dateformat')
const v_m = require('../validation_messages') const v_m = require('../validation_messages')
module.exports.create = [ module.exports.create = [
[ [
body('fa_name') body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title), .notEmpty().withMessage(v_m['fa'].required.title),
body('en_name') body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title) .notEmpty().withMessage(v_m['fa'].required.title)
], ],
(req, res) => { (req, res) => {
const errors = validationResult(req) const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = { const data = {
category_details: { category_details: {
fa: { fa: {
name: req.body.fa_name name: req.body.fa_name
}, },
en: { en: {
name: req.body.en_name name: req.body.en_name
} }
}, },
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
} }
const category = new ProductCategory(data) const category = new ProductCategory(data)
category.save(err => { category.save(err => {
if (err) return res.status(500).json({message: err}) if (err) return res.status(500).json({message: err})
return res.json({message: v_m['fa'].response.success_save}) return res.json({message: v_m['fa'].response.success_save})
}) })
} }
] ]
module.exports.getAll = [ module.exports.getAll = [
(req, res) => { (req, res) => {
ProductCategory.find({}, (err, categories) => { ProductCategory.find({}, (err, categories) => {
if (err) return res.status(500).json({message: err}) if (err) return res.status(500).json({message: err})
return res.json(categories) return res.json(categories)
}) })
} }
] ]
module.exports.getOne = [ module.exports.getOne = [
(req, res) => { (req, res) => {
ProductCategory.findById(req.params.id, (err, category) => { ProductCategory.findById(req.params.id, (err, category) => {
if (err) console.log(err) if (err) console.log(err)
return res.json(category) return res.json(category)
}) })
} }
] ]
module.exports.update = [ module.exports.update = [
[ [
body('fa_name') body('fa_name')
.notEmpty().withMessage(v_m['fa'].required.title), .notEmpty().withMessage(v_m['fa'].required.title),
body('en_name') body('en_name')
.notEmpty().withMessage(v_m['fa'].required.title) .notEmpty().withMessage(v_m['fa'].required.title)
], ],
(req, res) => { (req, res) => {
// check validation results // check validation results
const errors = validationResult(req) const errors = validationResult(req)
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
const data = { const data = {
category_details: { category_details: {
fa: { fa: {
name: req.body.fa_name name: req.body.fa_name
}, },
en: { en: {
name: req.body.en_name name: req.body.en_name
} }
} },
} updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
}
ProductCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => { ProductCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
if (err) return res.status(404).json({message: err}) if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_save}) return res.json({message: v_m['fa'].response.success_save})
}) })
} }
] ]
module.exports.delete = [ module.exports.delete = [
(req, res) => { (req, res) => {
Product.findOne({category: req.params.id}, (err, product) => { Product.findOne({category: req.params.id}, (err, product) => {
if (err) console.log(err) if (err) console.log(err)
if (product) return res.status(400).json({message: 'این دسته بندی دارای محصول است.'}) if (product) return res.status(400).json({message: 'این دسته بندی دارای محصول است.'})
else { else {
ProductCategory.findByIdAndDelete(req.params.id, (err, category) => { ProductCategory.findByIdAndDelete(req.params.id, (err, category) => {
if (err) return res.status(404).json({message: err}) if (err) return res.status(404).json({message: err})
return res.json({message: v_m['fa'].response.success_remove}) 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') const mongoose = require('mongoose')
function catalog(pdf) { function catalog(pdf) {
return '/uploads/pdf/' + pdf if (pdf) return '/uploads/pdf/' + pdf
} }
const MainCatalogSchema = mongoose.Schema({ const MainCatalogSchema = mongoose.Schema({
file: {type: String, get: catalog}, file: {
created_at: String fa: {type: String, get: catalog},
en: {type: String, get: catalog}
},
created_at: String,
updated_at: String
}, { }, {
toObject: {getters: true}, toObject: {getters: true},
toJSON: {getters: true} toJSON: {getters: true}
}) })
module.exports = mongoose.model('MainCatalog', MainCatalogSchema) module.exports = mongoose.model('MainCatalog', MainCatalogSchema)
+68 -63
View File
@@ -1,84 +1,89 @@
const mongoose = require('mongoose') const mongoose = require('mongoose')
function productImage(img) { function productImage(img) {
return '/uploads/images/products/' + img if (img) return '/uploads/images/products/' + img
} }
function productPDF(file) { function productPDF(file) {
return '/uploads/pdf/' + file if (file) return '/uploads/pdf/' + file
} }
const ProductImageSchema = mongoose.Schema({ const ProductImageSchema = mongoose.Schema({
image: {type: String, get: productImage}, image: {type: String, get: productImage},
created_at: String created_at: String
}, { }, {
toObject: {getters: true}, toObject: {getters: true},
toJSON: {getters: true} toJSON: {getters: true}
}) })
const ProductPDFSchema = mongoose.Schema({ const ProductPDFSchema = mongoose.Schema({
file: {type: String, get: productPDF}, file: {
pdf_details: { fa: {type: String, get: productPDF},
fa: { en: {type: String, get: productPDF}
name: String },
}, pdf_details: {
en: { fa: {
name: String name: String
} },
}, en: {
created_at: String name: String
}
},
created_at: String
}, { }, {
toObject: {getters: true}, toObject: {getters: true},
toJSON: {getters: true} toJSON: {getters: true}
}) })
const ProductSchema = mongoose.Schema({ const ProductSchema = mongoose.Schema({
cover: {type: String, get: productImage}, cover: {type: String, get: productImage},
images: [ProductImageSchema], thumb: {type: String, get: productImage},
more_section_image1: {type: String, get: productImage}, images: [ProductImageSchema],
more_section_image2: {type: String, get: productImage}, more_section_image1: {type: String, get: productImage},
render_image1: {type: String, get: productImage}, more_section_image2: {type: String, get: productImage},
render_image2: {type: String, get: productImage}, render_image1: {type: String, get: productImage},
chart_image: {type: String, get: productImage}, render_image2: {type: String, get: productImage},
pdf_files: [ProductPDFSchema], chart_image: {type: String, get: productImage},
category: String, pdf_files: [ProductPDFSchema],
more_section: {type: Boolean, default: true}, category: String,
download_section: {type: Boolean, default: true}, more_section: {type: Boolean, default: true},
product_details: { download_section: {type: Boolean, default: true},
fa: { favorite: {type: Boolean, default: false},
name: String, product_details: {
short_description: String, fa: {
page_title: String, name: String,
page_description: String, short_description: String,
more_title1: String, page_title: String,
more_description1: String, page_description: String,
more_title2: String, more_title1: String,
more_description2: String, more_description1: String,
render_caption1: String, more_title2: String,
render_caption2: String, more_description2: String,
chart_title: String, render_caption1: String,
chart_description: String render_caption2: String,
}, chart_title: String,
en: { chart_description: String
name: String, },
short_description: String, en: {
page_title: String, name: String,
page_description: String, short_description: String,
more_title1: String, page_title: String,
more_description1: String, page_description: String,
more_title2: String, more_title1: String,
more_description2: String, more_description1: String,
render_caption1: String, more_title2: String,
render_caption2: String, more_description2: String,
chart_title: String, render_caption1: String,
chart_description: String render_caption2: String,
} chart_title: String,
}, chart_description: String
created_at: String, }
updated_at: String },
created_at: String,
updated_at: String
}, { }, {
toObject: {getters: true}, toObject: {getters: true},
toJSON: {getters: true} toJSON: {getters: true}
}) })
+7 -1
View File
@@ -12,6 +12,7 @@ const contactPageController = require('../controllers/contactPageController')
const contactUsReasonController = require('../controllers/contactUsReasonController') const contactUsReasonController = require('../controllers/contactUsReasonController')
const mainCatalogController = require('../controllers/mainCatalogController') const mainCatalogController = require('../controllers/mainCatalogController')
const historyController = require('../controllers/historyController') const historyController = require('../controllers/historyController')
const calculationModule = require('../controllers/calculationModule')
/////////////////////////////////////////////////////////// routes /////////////////////////////////////////////////////////// routes
//////////////// slider //////////////// slider
@@ -31,7 +32,7 @@ router.get('/productCategories', productCategoryController.getAll)
router.get('/productCategories/:id', productCategoryController.getOne) router.get('/productCategories/:id', productCategoryController.getOne)
//////////////// products //////////////// products
router.get('/products/:category', productController.getAllProductsByCategory) router.get('/favoriteProducts', productController.getFavoriteProducts)
router.get('/products/', productController.getAllProducts) router.get('/products/', productController.getAllProducts)
router.get('/product/:id', productController.getOneProduct) router.get('/product/:id', productController.getOneProduct)
@@ -51,4 +52,9 @@ router.get('/catalog', mainCatalogController.get)
router.get('/history', historyController.getAll) router.get('/history', historyController.getAll)
router.get('/history/:id', historyController.getOne) 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 module.exports = router
+30 -7
View File
@@ -127,7 +127,7 @@ $panelBg: #fff;
padding: 0 15px; padding: 0 15px;
position: fixed; position: fixed;
top: 56px; top: 56px;
left: 15px; left: 0;
z-index: 5; z-index: 5;
h2 { h2 {
@@ -177,10 +177,11 @@ $panelBg: #fff;
} }
.admin--sidebar { .admin--sidebar {
min-height: calc(100vh - 55px); height: calc(100vh - 55px);
background: $sidebar; background: $sidebar;
flex-basis: 300px; flex-basis: 300px;
border-left: 1px solid $borders; border-left: 1px solid $borders;
overflow: auto;
ul { ul {
width: 100%; width: 100%;
@@ -231,6 +232,23 @@ $panelBg: #fff;
.admin-user { .admin-user {
padding: 20px 15px; padding: 20px 15px;
color: $usernameColor; 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 { h2 {
font-size: 25px !important; font-size: 25px !important;
@@ -254,6 +272,11 @@ $panelBg: #fff;
} }
} }
} }
.sidebar--content {
height: 100%;
overflow: auto;
}
} }
.admin--header { .admin--header {
@@ -320,6 +343,11 @@ $panelBg: #fff;
text-align: center; text-align: center;
} }
.err {
color: red;
font-size: 13px;
}
} }
pre { pre {
@@ -382,11 +410,6 @@ html:lang(fa) {
margin-top: 50px; margin-top: 50px;
} }
.err {
color: red;
font-size: 13px;
}
.el-upload__input { .el-upload__input {
display: none !important; 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'); 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-face {
font-family: 'sahel-black'; font-family: 'sahel-black';
@@ -20,6 +14,22 @@
url("../fonts/sahel/Sahel-Black-FD.woff") format('woff'); 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 ////// diodrum
@font-face { @font-face {
font-family: 'diodrum'; font-family: 'diodrum';
+25 -2
View File
@@ -11,8 +11,8 @@ body {
} }
} }
p, a, span, b { p, a, span, b, label, strong, small, li {
font-family: 'sahel'; font-family: 'sahel', 'diodrum', sans-serif;
color: rgba(0, 0, 0, 0.7); color: rgba(0, 0, 0, 0.7);
line-height: 1.6em; line-height: 1.6em;
@@ -67,6 +67,24 @@ section {
padding: 0 0 100px; 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 { @keyframes loading {
0% { 0% {
@include transform(rotateZ(0)); @include transform(rotateZ(0));
@@ -168,6 +186,11 @@ section {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
background: $darkGray; background: $darkGray;
direction: ltr;
&:lang(en) {
direction: rtl;
}
.catalog-download { .catalog-download {
display: block; display: block;
+245 -72
View File
@@ -341,7 +341,7 @@
.hero { .hero {
.bg { .bg {
background-image: url("../img/about/about-hero.jpg"); background-image: url("../img/services/hero.jpg");
} }
} }
@@ -557,7 +557,7 @@
.hero { .hero {
.bg { .bg {
background-image: url('../img/services/services-hero.jpg'); background-image: url('../img/services/hero.jpg');
} }
} }
@@ -639,7 +639,7 @@
.products--page { .products--page {
.hero { .hero {
.bg { .bg {
background-image: url('../img/products/products-hero.jpg'); background-image: url('../img/products/hero.jpg');
} }
} }
@@ -760,7 +760,6 @@
///////////////////////////// products page ///////////////////////////// products page
.product-details--page { .product-details--page {
.hero { .hero {
.bg { .bg {
background-image: url('../img/products/products-hero.jpg'); background-image: url('../img/products/products-hero.jpg');
@@ -782,14 +781,7 @@
} }
img { img {
width: 50%; width: 100%;
@media (max-width: 1200px) {
width: 80%;
}
@media (max-width: 992px) {
width: 100%;
}
} }
} }
@@ -818,20 +810,28 @@
} }
#images { #images {
margin-top: 250px; margin-top: 80px;
img { img {
width: 60%; width: 60%;
min-height: 100px;
object-fit: cover;
margin: 0 auto; margin: 0 auto;
cursor: pointer; cursor: pointer;
border: 3px solid transparent;
@extend %defaultTransition;
&.selected {
border: 3px solid $red;
}
} }
} }
} }
} }
.s2 { .s2 {
margin-top: 100px; margin-top: 200px;
.parts { .parts {
margin-top: 100px; margin-top: 100px;
@@ -877,6 +877,10 @@
&.p3 { &.p3 {
text-align: center; text-align: center;
img {
width: 100%;
}
} }
&.p4 { &.p4 {
@@ -1117,8 +1121,16 @@
text-align: right; text-align: right;
margin-bottom: 30px; margin-bottom: 30px;
span {
font-family: 'sahel', sans-serif;
}
&:lang(en) { &:lang(en) {
text-align: left; text-align: left;
span {
font-family: 'diodrum', sans-serif;
}
} }
.category { .category {
@@ -1178,6 +1190,14 @@
text-align: center; text-align: center;
margin-bottom: 80px; margin-bottom: 80px;
span {
font-family: 'sahel', sans-serif;
&:lang(en) {
font-family: 'diodrum', sans-serif;
}
}
.category { .category {
display: block; display: block;
margin-bottom: 10px; 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 { .s2 {
@@ -1290,13 +1264,31 @@
li { li {
margin-bottom: 30px; margin-bottom: 30px;
i { a {
color: $red; @extend %defaultTransition;
margin-left: 5px;
&:lang(en) { &:hover {
margin-left: 0; color: $theme;
margin-right: 5px;
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: decimal;
list-style-position: outside; list-style-position: outside;
p { a {
direction: ltr; 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 { h2 {
margin-top: 80px; margin-top: 80px;
margin-bottom: 30px; margin-bottom: 30px;
@@ -1482,29 +1491,48 @@
.s2 { .s2 {
.app { .app {
$appLayoutPadding: 55px;
@include transition(0.1s);
.appTitle { .appTitle {
text-align: center; text-align: center;
.title {
font-size: 30px;
@media (max-width: 1400px) {
font-size: 25px;
}
}
} }
.appMethod { .appMethod {
text-align: center; text-align: center;
margin-bottom: 50px; margin-bottom: 50px;
background: $red; background: $theme;
padding: 15px; padding: 15px;
.txt {
display: inline-block;
margin: 0 10px 10px;
}
span { span {
color: #fff; color: #fff;
} }
.el-radio-button__orig-radio:checked + .el-radio-button__inner { .el-radio-button__orig-radio:checked + .el-radio-button__inner {
background-color: $darkGray; background-color: $darkGray;
border-color: $darkGray; border-color: #fff;
@include boxShadow(-1px 0 0 0 $darkGray); @include boxShadow(-1px 0 0 0 $darkGray);
} }
.el-radio-button .el-radio-button__inner { .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 { .el-radio-button.is-active .el-radio-button__inner {
@@ -1513,8 +1541,8 @@
} }
.appLayout { .appLayout {
padding: 55px; padding: $appLayoutPadding;
background: $red; background: $theme;
height: 100%; height: 100%;
@include boxSizing(border-box); @include boxSizing(border-box);
@@ -1608,6 +1636,10 @@
color: $darkGray; color: $darkGray;
} }
} }
.err {
color: $red;
}
} }
.el-input { .el-input {
@@ -1616,6 +1648,35 @@
//@media (max-width: 600px) { //@media (max-width: 600px) {
// width: 100%; // 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 { .el-select {
@@ -1630,6 +1691,118 @@
margin-left: 20px; 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 "variables";
@import "mixins"; @import "mixins";
@import "extentions"; @import "extentions";
+42 -47
View File
@@ -1,53 +1,48 @@
<template> <template>
<footer class="footer"> <footer class="footer">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 col-md-8 mb-3 mb-md-0 links"> <div class="col-12 col-md-8 mb-3 mb-md-0 links">
<logo/> <logo/>
<div class="box"> <div class="box">
<p><b>{{staticData.t1}}</b> <span>{{staticData.address}}</span></p> <p><b>{{ staticData.t1 }}</b> <span>{{ $store.state.global.address[$route.params.lang] }}</span></p>
<!-- <hr>--> <!-- <hr>-->
<p class="red"> <p class="red">
<b>{{staticData.t2}}</b> <a :href="'tel:' + staticData.fax">{{staticData.tell}}</a> <b>{{ staticData.t2 }}</b> <a :href="'tel:' + $store.state.global.tell">{{ $store.state.global.tell_view }}</a>
&nbsp &nbsp - &nbsp &nbsp &nbsp &nbsp - &nbsp &nbsp
<b>{{staticData.t3}}</b> <a :href="'tel:' + staticData.fax">{{staticData.fax}}</a> <b>{{ staticData.t3 }}</b> <a :href="'tel:' + $store.state.global.fax">{{ $store.state.global.fax_view }}</a>
</p> </p>
</div> </div>
</div> </div>
<div class="col-12 col-md-4 social"> <div class="col-12 col-md-4 social">
<ul class="social-links"> <ul class="social-links">
<li> <li>
<a href="" target="_blank"> <a :href="$store.state.global.instagram_url" target="_blank">
<em class="fab fa-facebook-f"></em> <i class="fab fa-instagram"></i>
</a> </a>
</li> </li>
<li> <li>
<a href="" target="_blank"> <a :href="$store.state.global.linkedin_url" target="_blank">
<em class="fab fa-twitter"></em> <i class="fab fa-linkedin-in"></i>
</a> </a>
</li> </li>
<li> </ul>
<a href="" target="_blank"> <p>{{ staticData.t5 }}</p>
<em class="fab fa-telegram-plane"></em> <p class="blue"><b>{{ staticData.t4 }}</b> <a :href="'mailto:' + $store.state.global.email">{{ $store.state.global.email }}</a></p>
</a> </div>
</li> </div>
</ul> </div>
<p>{{staticData.t5}}</p> <div class="footer-bar"></div>
<p class="blue"><b>{{staticData.t4}}</b> <a :href="'mailto:' + staticData.email">{{staticData.email}}</a></p> </footer>
</div>
</div>
</div>
<div class="footer-bar"></div>
</footer>
</template> </template>
<script> <script>
export default { export default {
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.footer[this.$route.params.lang] return this.$store.state.staticData.footer[this.$route.params.lang]
} }
} }
} }
</script> </script>
+43 -48
View File
@@ -1,53 +1,48 @@
<template> <template>
<footer class="footer footer--home"> <footer class="footer footer--home">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="xol-12 col-md-8 mb-5 mb-md-0 links"> <div class="xol-12 col-md-8 mb-5 mb-md-0 links">
<div class="logo"> <div class="logo">
<logo/> <logo/>
<span>{{staticData.t6}}</span> <span>{{ staticData.t6 }}</span>
</div> </div>
<div class="box"> <div class="box">
<p><b>{{staticData.t1}}</b> <span>{{staticData.address}}</span></p> <p><b>{{ staticData.t1 }}</b> <span>{{ $store.state.global.address[$route.params.lang] }}</span></p>
<hr> <hr>
<p class="red"><b>{{staticData.t2}}</b> <a :href="'tel:' + staticData.fax">{{staticData.tell}}</a></p> <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:' + staticData.fax">{{staticData.fax}}</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"> <ul class="social-links red">
<li> <li>
<a href="" target="_blank"> <a :href="$store.state.global.instagram_url" target="_blank">
<em class="fab fa-facebook-f"></em> <i class="fab fa-instagram"></i>
</a> </a>
</li> </li>
<li> <li>
<a href="" target="_blank"> <a :href="$store.state.global.linkedin_url" target="_blank">
<em class="fab fa-twitter"></em> <i class="fab fa-linkedin-in"></i>
</a> </a>
</li> </li>
<li> </ul>
<a href="" target="_blank"> <p class="blue"><b>{{ staticData.t4 }}</b> <a :href="'mailto:' + $store.state.global.email">{{ $store.state.global.email }}</a></p>
<em class="fab fa-telegram-plane"></em> </div>
</a> </div>
</li> <div class="xol-12 col-md-4 map">
</ul> <img src="~/assets/img/footer-map.jpg" alt="">
<p class="blue"><b>{{staticData.t4}}</b> <a :href="'mailto:' + staticData.email">{{staticData.email}}</a></p> <p>{{ staticData.t5 }}</p>
</div> </div>
</div> </div>
<div class="xol-12 col-md-4 map"> </div>
<img src="~/assets/img/footer-map.jpg" alt=""> <div class="footer-bar"></div>
<p>{{staticData.t5}}</p> </footer>
</div>
</div>
</div>
<div class="footer-bar"></div>
</footer>
</template> </template>
<script> <script>
export default { export default {
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.footer[this.$route.params.lang] return this.$store.state.staticData.footer[this.$route.params.lang]
} }
} }
} }
</script> </script>
+166 -166
View File
@@ -1,176 +1,176 @@
<template> <template>
<header class="header"> <header class="header">
<div class="lang-bar"> <div class="lang-bar">
<a :href="catalog.file" target="_blank" class="catalog-download"> <a v-if="catalog && catalog.file" :href="catalog.file[$route.params.lang]" target="_blank" class="catalog-download">
<span>{{staticData.catalog}}</span> <span>{{ staticData.catalog }}</span>
<span>&nbsp;</span> <span>&nbsp;</span>
<i class="fas fa-download"></i> <i class="fas fa-download"></i>
</a> </a>
<div class="dropdown" @mouseenter="drop" @mouseleave="drop"> <div class="dropdown" @mouseenter="drop" @mouseleave="drop">
<div class="title"> <div class="title">
<p class="current-lang"> <p class="current-lang">
<span>FA / EN</span> <span>FA / EN</span>
<i class="fas fa-sort-down"></i> <i class="fas fa-sort-down"></i>
</p> </p>
</div> </div>
<div class="dropMenu"> <div class="dropMenu">
<div class="drop-item"> <div class="drop-item">
<nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'fa'}}">FA</nuxt-link> <nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'fa'}}">FA</nuxt-link>
</div> </div>
<div class="drop-item"> <div class="drop-item">
<nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'en'}}">EN</nuxt-link> <nuxt-link :to="{to: this.$route.fullPath, params: {lang: 'en'}}">EN</nuxt-link>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="container-fluid"> <div class="container-fluid">
<nav class="row align-items-center"> <nav class="row align-items-center">
<!-- desktop --> <!-- desktop -->
<div class="col-12 d-none d-md-block links"> <div class="col-12 d-none d-md-block links">
<div class="container-fluid"> <div class="container-fluid">
<ul class="row justify-content-start"> <ul class="row justify-content-start">
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class=""> <nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a class="logo"> <a class="logo">
<Logo/> <Logo/>
</a> </a>
</nuxt-link> </nuxt-link>
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class=""> <nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.home}}</a> <a>{{ staticData.home }}</a>
</nuxt-link> </nuxt-link>
<nuxt-link :to="{name: 'lang-about',params: {lang: $route.params.lang}}" tag="li" exact class=""> <nuxt-link :to="{name: 'lang-about',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.about}}</a> <a>{{ staticData.about }}</a>
</nuxt-link> </nuxt-link>
<nuxt-link :to="{name: 'lang-services',params: {lang: $route.params.lang}}" tag="li" exact class=""> <nuxt-link :to="{name: 'lang-services',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.services}}</a> <a>{{ staticData.services }}</a>
</nuxt-link> </nuxt-link>
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" tag="li" class=""> <nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" tag="li" class="">
<a>{{staticData.products}}</a> <a>{{ staticData.products }}</a>
</nuxt-link> </nuxt-link>
<nuxt-link :to="{name: 'lang-projects',params: {lang: $route.params.lang}}" tag="li" exact class=""> <nuxt-link :to="{name: 'lang-projects',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.projects}}</a> <a>{{ staticData.projects }}</a>
</nuxt-link> </nuxt-link>
<li class="tech_info" @mouseenter="tech_info" @mouseleave="tech_info" <li class="tech_info" @mouseenter="tech_info" @mouseleave="tech_info"
:class="$route.name === 'lang-tech-gDesign' || :class="$route.name === 'lang-tech-gDesign' ||
$route.name === 'lang-tech-gStandard' || $route.name === 'lang-tech-gStandard' ||
$route.name === 'lang-tech-gTech' || $route.name === 'lang-tech-gTech' ||
$route.name === 'lang-tech-gUsage' ? 'active' : null"> $route.name === 'lang-tech-gUsage' ? 'active' : null">
<a>{{staticData.tech_info}}</a> <a>{{ staticData.tech_info }}</a>
<div class="drop-down"> <div class="drop-down">
<ul> <ul>
<li :class="$route.name === 'lang-tech-gTech' ? 'sub-menu-active' : null"> <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> <nuxt-link :to="{name: 'lang-tech-gTech',params: {lang: $route.params.lang}}">{{ staticData.ti_1 }}</nuxt-link>
</li> </li>
<li :class="$route.name === 'lang-tech-gStandard' ? 'sub-menu-active' : null"> <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> <nuxt-link :to="{name: 'lang-tech-gStandard',params: {lang: $route.params.lang}}">{{ staticData.ti_2 }}</nuxt-link>
</li> </li>
<li :class="$route.name === 'lang-tech-gDesign' ? 'sub-menu-active' : null"> <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> <nuxt-link :to="{name: 'lang-tech-gDesign',params: {lang: $route.params.lang}}">{{ staticData.ti_3 }}</nuxt-link>
</li> </li>
<li :class="$route.name === 'lang-tech-gUsage' ? 'sub-menu-active' : null"> <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> <nuxt-link :to="{name: 'lang-tech-gUsage',params: {lang: $route.params.lang}}">{{ staticData.ti_4 }}</nuxt-link>
</li> </li>
</ul> </ul>
</div> </div>
</li> </li>
<nuxt-link :to="{name: 'lang-blog',params: {lang: $route.params.lang}}" tag="li" class=""> <nuxt-link :to="{name: 'lang-blog',params: {lang: $route.params.lang}}" tag="li" class="">
<a>{{staticData.blog}}</a> <a>{{ staticData.blog }}</a>
</nuxt-link> </nuxt-link>
<nuxt-link :to="{name: 'lang-contact',params: {lang: $route.params.lang}}" tag="li" exact class=""> <nuxt-link :to="{name: 'lang-contact',params: {lang: $route.params.lang}}" tag="li" exact class="">
<a>{{staticData.contact}}</a> <a>{{ staticData.contact }}</a>
</nuxt-link> </nuxt-link>
</ul> </ul>
</div> </div>
</div> </div>
<!-- mobile --> <!-- mobile -->
<div class="col-12 d-md-none links mobile"> <div class="col-12 d-md-none links mobile">
<div class="container-fluid"> <div class="container-fluid">
<ul class="row"> <ul class="row">
<li class="col"> <li class="col">
<nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" exact class="logo"> <nuxt-link :to="{name: 'lang',params: {lang: $route.params.lang}}" exact class="logo">
<Logo/> <Logo/>
</nuxt-link> </nuxt-link>
</li> </li>
<li class="col menu"> <li class="col menu">
<div id="menuBtn" @click="offCanvas"> <div id="menuBtn" @click="offCanvas">
<div class="bars b1"></div> <div class="bars b1"></div>
<div class="bars b2"></div> <div class="bars b2"></div>
<div class="bars b3"></div> <div class="bars b3"></div>
</div> </div>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</nav> </nav>
</div> </div>
</header> </header>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
catalog: null catalog: null
} }
}, },
async fetch() { async fetch() {
let catalog = await this.$axios.get('/api/public/catalog') let catalog = await this.$axios.get('/api/public/catalog')
this.catalog = catalog.data this.catalog = catalog.data
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.header[this.$route.params.lang] return this.$store.state.staticData.header[this.$route.params.lang]
}, },
offCanvasLiTL() { offCanvasLiTL() {
if (process.server) return null if (process.server) return null
else return this.$gsap.timeline({delay: 0.3, paused: true}) else return this.$gsap.timeline({delay: 0.3, paused: true})
.fromTo($('.offCanvas ul li'), { .fromTo($('.offCanvas ul li'), {
x: this.$route.params.lang === 'fa' ? 10 : -10, x: this.$route.params.lang === 'fa' ? 10 : -10,
opacity: 0 opacity: 0
}, { }, {
x: 0, x: 0,
opacity: 1, opacity: 1,
duration: 0.4, duration: 0.4,
stagger: 0.03 stagger: 0.03
}) })
} }
}, },
methods: { methods: {
drop() { drop() {
$('.dropdown').toggleClass('dropdown-active') $('.dropdown').toggleClass('dropdown-active')
}, },
tech_info() { tech_info() {
const el = $('.tech_info .drop-down') const el = $('.tech_info .drop-down')
if (el.height() === 0) { if (el.height() === 0) {
el.css({height: $('.tech_info .drop-down ul').height()}) el.css({height: $('.tech_info .drop-down ul').height()})
} else { } else {
el.css({height: 0}) 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()
})
} }
} },
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> </script>
+29 -29
View File
@@ -1,42 +1,42 @@
<template> <template>
<ul> <ul>
<admin-aside-item icon="fas fa-home" :link="{name: 'admin'}" text="صفحه اصلی"/> <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="fas fa-presentation" :link="{name: 'admin-slider'}" text="اسلایدر"/>
<admin-aside-item icon="fa fa-gift" text="محصولات" :hasChild="true"> <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'}" text="لیست محصولات"/>
<admin-aside-item :link="{name: 'admin-products-category'}" text="دسته بندی محصولات"/> <admin-aside-item :link="{name: 'admin-products-category'}" text="دسته بندی محصولات"/>
</admin-aside-item> </admin-aside-item>
<admin-aside-item icon="fa fa-newspaper" text="بلاگ" :hasChild="true"> <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'}" text="لیست بلاگ"/>
<admin-aside-item :link="{name: 'admin-blog-category'}" text="دسته بندی بلاگ"/> <admin-aside-item :link="{name: 'admin-blog-category'}" text="دسته بندی بلاگ"/>
</admin-aside-item> </admin-aside-item>
<admin-aside-item icon="fas fa-bags-shopping" :link="{name: 'admin-projects'}" text="پروژه ها"/> <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-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-envelope" :badge="$store.state.admin.unread" :link="{name: 'admin-messages'}" text="پیام های ارتباط با ما"/>
<admin-aside-item icon="fas fa-file-pdf" :link="{name: 'admin-catalog'}" text="آپلود فایل کاتالوگ"/> <admin-aside-item icon="fas fa-file-pdf" :link="{name: 'admin-catalog'}" text="آپلود فایل کاتالوگ"/>
</ul> </ul>
</template> </template>
<script> <script>
export default { export default {
mounted() { mounted() {
if (this.$auth.loggedIn) { if (this.$auth.loggedIn) {
this.$axios.get('/api/private/contact') this.$axios.get('/api/private/contact')
.then(response => { .then(response => {
let unread = response.data.filter(item => { let unread = response.data.filter(item => {
return !item.read return !item.read
}) })
this.$store.commit('admin/unreadCount', unread.length) this.$store.commit('admin/unreadCount', unread.length)
}) })
} }
} }
} }
</script> </script>
+39 -37
View File
@@ -1,45 +1,47 @@
<template> <template>
<div class="admin" v-if="$auth.loggedIn && $auth.user.scope.includes('admin')"> <div class="admin" v-if="$auth.loggedIn && $auth.user.scope.includes('admin')">
<!-- <div class="admin">--> <!-- <div class="admin">-->
<div class="admin"> <div class="admin">
<admin-header/> <admin-header/>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<aside class="admin--sidebar"> <aside class="admin--sidebar">
<admin-user v-if="$auth.loggedIn && $auth.user.scope.includes('admin')" :user="$auth.user.name"/> <div class="sidebar--content">
<admin-aside/> <admin-user v-if="$auth.loggedIn && $auth.user.scope.includes('admin')" :user="$auth.user.name"/>
</aside> <admin-aside/>
<div class="admin--content"> </div>
<nuxt/> </aside>
</div> <div class="admin--content">
</div> <nuxt/>
</div> </div>
</div> </div>
</div> </div>
<div class="admin" v-else> </div>
<div class="admin--content" style="flex-basis: 100%!important;height: 100%!important;"> </div>
<div class="container"> <div class="admin" v-else>
<div class="row"> <div class="admin--content" style="flex-basis: 100%!important;height: 100%!important;">
<nuxt/> <div class="container">
</div> <div class="row">
</div> <nuxt/>
</div> </div>
</div> </div>
</div>
</div>
</template> </template>
<script> <script>
export default { export default {
head() { head() {
return { return {
htmlAttrs: { htmlAttrs: {
lang: 'fa' lang: 'fa'
} }
} }
}, },
middleware: 'auth-admin' middleware: 'auth-admin'
} }
</script> </script>
<style lang="scss"> <style lang="scss">
@import "assets/admin/sass/admin"; @import "assets/admin/sass/admin";
</style> </style>
+42 -35
View File
@@ -1,43 +1,50 @@
<template> <template>
<div> <div>
<SiteHeader/> <SiteHeader/>
<nuxt/> <nuxt/>
<SiteFooterHomePage v-if="this.$route.name === 'lang'"/> <SiteFooterHomePage v-if="this.$route.name === 'lang'"/>
<SiteFooterGlobal v-else/> <SiteFooterGlobal v-else/>
<off-canvas/> <off-canvas/>
<page-load/> <page-load/>
<pre-loader/> <pre-loader/>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
mounted() { mounted() {
////////////////////////////////////////// global router guards ////////////////////////////////////////// global router guards
this.$router.beforeEach((to, from, next) => { this.$router.beforeEach((to, from, next) => {
this.$gsap.timeline({ this.$gsap.timeline({
onComplete: () => { onComplete: () => {
next() next()
} }
}) })
.to($('.page-load'), {autoAlpha: 1, duration: 0.3}) .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 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}) .fromTo($('.page-load p'), {opacity: 0, scale: 1, y: 10}, {opacity: 1, y: 0, duration: 0.15})
}) })
this.$router.afterEach((to, from) => { this.$router.afterEach((to, from) => {
this.$gsap.timeline({delay: 0.3}) this.$gsap.timeline({delay: 0.3})
.to($('.page-load p,.page-load svg'), {opacity: 0, scale: 0.5, duration: 0.15}) .to($('.page-load p,.page-load svg'), {opacity: 0, scale: 0.5, duration: 0.15})
.to($('.page-load'), {autoAlpha: 0, duration: 0.5}) .to($('.page-load'), {autoAlpha: 0, duration: 0.5})
}) })
},
head() {
return {
htmlAttrs: {
lang: this.$route.params.lang
}, },
head() { meta: [
return { {
htmlAttrs: { hid: 'description',
lang: this.$route.params.lang name: 'description',
} content: this.$store.state.global.meta_description[this.$route.params.lang]
} }
} ],
} }
}
}
</script> </script>
+8 -8
View File
@@ -1,11 +1,11 @@
export default function ({route, redirect, error}) { export default function ({route, redirect, error}) {
///////////// redirect to default local ///////////// redirect to default local
if (route.path === '/') return redirect('/fa') if (route.path === '/') return redirect('/fa')
///////////// local check ///////////// local check
const lang = ['fa', 'en'] const lang = ['fa', 'en']
const isLocal = lang.includes(route.params.lang) const isLocal = lang.includes(route.params.lang)
const isAdmin = route.path.includes('/admin') const isAdmin = route.path.includes('/admin')
if (isLocal || isAdmin) return null if (isLocal || isAdmin) return null
else error({statusCode: 404, message: 'Page Not Found'}) else error({statusCode: 404, message: 'Page Not Found'})
} }
+84 -81
View File
@@ -1,92 +1,95 @@
const webpack = require("webpack") const webpack = require("webpack")
export default { export default {
// Global page headers (https://go.nuxtjs.dev/config-head) // Global page headers (https://go.nuxtjs.dev/config-head)
head: { head: {
title: 'Arak Rail', title: 'اراک ریل',
meta: [ meta: [
{charset: 'utf-8'}, {charset: 'utf-8'},
{name: 'viewport', content: 'width=device-width, initial-scale=1'}, {name: 'viewport', content: 'width=device-width, initial-scale=1'},
{hid: 'description', name: 'description', content: ''}, {name: 'theme-color', content: '#303030'},
{name: 'theme-color', content: '#303030'}, ],
], link: [
link: [ {rel: 'icon', type: 'image/x-icon', href: '/favicon.png'}
{rel: 'icon', type: 'image/x-icon', href: '/favicon.png'} ]
] },
},
// Global CSS (https://go.nuxtjs.dev/config-css) // Global CSS (https://go.nuxtjs.dev/config-css)
loading: { loading: {
color: '#1B407C' color: '#1B407C'
}, },
css: [ css: [
'slick-carousel/slick/slick.css', 'slick-carousel/slick/slick.css',
'slick-carousel/slick/slick-theme.css', 'slick-carousel/slick/slick-theme.css',
'element-ui/lib/theme-chalk/index.css', 'element-ui/lib/theme-chalk/index.css',
'~/assets/css/bootstrap-grid.css', '~/assets/css/bootstrap-grid.css',
'~/assets/css/reset-css.css', '~/assets/css/reset-css.css',
'~/assets/css/fontawesome/css/all.min.css', '~/assets/css/fontawesome/css/all.min.css',
'~/assets/sass/main.scss' '~/assets/sass/main.scss'
], ],
// Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins) // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
plugins: [ plugins: [
'@/plugins/element-ui', '@/plugins/element-ui',
'@/plugins/ckEditor.client', '@/plugins/ckEditor.client',
'@/plugins/datePicker.client', '@/plugins/datePicker.client',
'@/plugins/gsap.client' '@/plugins/gsap.client'
], ],
// Auto import components (https://go.nuxtjs.dev/config-components) // Auto import components (https://go.nuxtjs.dev/config-components)
components: true, components: true,
// Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules) // Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
buildModules: [], buildModules: [],
// Modules (https://go.nuxtjs.dev/config-modules) // Modules (https://go.nuxtjs.dev/config-modules)
modules: [ modules: [
// https://go.nuxtjs.dev/axios // https://go.nuxtjs.dev/axios
'@nuxtjs/axios', '@nuxtjs/axios',
'@nuxtjs/auth' '@nuxtjs/auth'
], ],
// Axios module configuration (https://go.nuxtjs.dev/config-axios) // Axios module configuration (https://go.nuxtjs.dev/config-axios)
axios: { axios: {
proxy: true proxy: true
}, },
proxy: { proxy: {
'/api': {target: 'http://127.0.0.1:7320'} '/api': {target: 'http://127.0.0.1:7320'}
}, },
// Build Configuration (https://go.nuxtjs.dev/config-build) // Build Configuration (https://go.nuxtjs.dev/config-build)
build: { build: {
transpile: [/^element-ui/], transpile: [/^element-ui/],
vendor: ["jquery"],
plugins: [new webpack.ProvidePlugin({$: "jquery"})] plugins: [new webpack.ProvidePlugin({
}, $: 'jquery',
router: { jQuery: 'jquery',
middleware: ['redirects'], 'window.jQuery': 'jquery'
linkActiveClass: 'active' })]
}, },
server: { router: {
host: '0.0.0.0', middleware: ['redirects'],
port: 7320 linkActiveClass: 'active'
}, },
serverMiddleware: ['~/api/index'], server: {
auth: { host: '0.0.0.0',
rewriteRedirects: true, port: 7320
redirect: false, },
strategies: { serverMiddleware: ['~/api/index'],
local: { auth: {
endpoints: { rewriteRedirects: true,
login: {url: '/api/auth/admin/login', method: 'post', propertyName: 'token'}, redirect: false,
logout: {url: '/api/auth/admin/logout', method: 'post'}, strategies: {
user: {url: '/api/auth/admin/user', method: 'get', propertyName: 'user'} local: {
}, endpoints: {
tokenRequired: true, login: {url: '/api/auth/admin/login', method: 'post', propertyName: 'token'},
tokenType: '', logout: {url: '/api/auth/admin/logout', method: 'post'},
globalToken: true, user: {url: '/api/auth/admin/user', method: 'get', propertyName: 'user'}
autoFetchUser: true },
} tokenRequired: true,
tokenType: '',
globalToken: true,
autoFetchUser: true
} }
} }
}
} }
+154 -154
View File
@@ -1,167 +1,167 @@
<template> <template>
<div class="page about--page"> <div class="page about--page">
<Hero :title="staticData.hero"/> <Hero :title="staticData.hero"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="parts p1"> <div class="parts p1">
<logo/> <logo/>
<span>{{staticData.s1.t1}}</span> <span>{{ staticData.s1.t1 }}</span>
<p>{{staticData.s1.t2}}</p> <p>{{ staticData.s1.t2 }}</p>
</div> </div>
<div class="parts p2 row"> <div class="parts p2 row">
<div class="col-12 col-lg-6 order-1 order-lg-0"> <div class="col-12 col-lg-6 order-1 order-lg-0">
<p>{{staticData.s1.t3}}</p> <p>{{ staticData.s1.t3 }}</p>
</div> </div>
<div class="col-12 col-lg-6 order-0 order-lg-1 mb-5 mb-lg-0"> <div class="col-12 col-lg-6 order-0 order-lg-1 mb-5 mb-lg-0">
<div class="imgBox anim-fadeIn"> <div class="imgBox anim-fadeIn">
<div class="img"> <div class="img">
<div class="shape"></div> <div class="shape"></div>
<img src="~/assets/img/about/about-s1-i1.jpg" alt=""> <img src="~/assets/img/about/about-s1-i1.jpg" alt="">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="parts p3 row"> <div class="parts p3 row">
<div class="col-12 col-lg-6 mb-5 mb-lg-0"> <div class="col-12 col-lg-6 mb-5 mb-lg-0">
<div class="imgBox imgBox-reverse anim-fadeIn"> <div class="imgBox imgBox-reverse anim-fadeIn">
<div class="img"> <div class="img">
<div class="shape reverse"></div> <div class="shape reverse"></div>
<img src="~/assets/img/about/about-s1-i2.jpg" alt=""> <img src="~/assets/img/about/about-s1-i2.jpg" alt="">
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 col-lg-6"> <div class="col-12 col-lg-6">
<p>{{staticData.s1.t4}}</p> <p>{{ staticData.s1.t4 }}</p>
</div> </div>
</div> </div>
<div class="parts p4 row"> <div class="parts p4 row">
<div class="col-12"> <div class="col-12">
<p>{{staticData.s1.t5}}</p> <p>{{ staticData.s1.t5 }}</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s2" v-if="history.length"> <section class="s2" v-if="history.length">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2 class="title title-shape-center">{{staticData.s2.t1}}</h2> <h2 class="title title-shape-center">{{ staticData.s2.t1 }}</h2>
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="timeline anim-fadeIn"> <div class="timeline anim-fadeIn">
<template v-for="(item,index) in history"> <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)"> <div class="circle" :key="item._id" :class="!index ? 'active' : null" :data-c-n="index" @click="activeHistory(item,index)">
<span>{{mDate(item.year)}}</span> <span>{{ mDate(item.year) }}</span>
</div> </div>
<div class="line" :key="item._id + 1" :data-l-n="index" v-if="index < history.length - 1"></div> <div class="line" :key="item._id + 1" :data-l-n="index" v-if="index < history.length - 1"></div>
</template> </template>
</div> </div>
<div class="timeline-content anim-fadeIn"> <div class="timeline-content anim-fadeIn">
<div class="row"> <div class="row">
<div class="col-12 col-md-6 order-1 order-md-0"> <div class="col-12 col-md-6 order-1 order-md-0">
<div class="txtBox"> <div class="txtBox">
<h5 ref="title">{{history[0].history_details[$route.params.lang].title}}</h5> <h5 ref="title">{{ history[0].history_details[$route.params.lang].title }}</h5>
<p ref="caption">{{history[0].history_details[$route.params.lang].caption}}</p> <p ref="caption">{{ history[0].history_details[$route.params.lang].caption }}</p>
</div> </div>
</div> </div>
<div class="col-12 col-md-6 order-0 order-md-1 mb-3 mb-md-0"> <div class="col-12 col-md-6 order-0 order-md-1 mb-3 mb-md-0">
<div class="imgBox" v-if="history.length"> <div class="imgBox" v-if="history.length">
<img ref="image" :src="history[0].image" :alt="history[0].history_details[$route.params.lang].title"> <img ref="image" :src="history[0].image" :alt="history[0].history_details[$route.params.lang].title">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s3"> <section class="s3">
<div class="container"> <div class="container">
<h2 class="title title-shape">{{staticData.s3.t1}}</h2> <h2 class="title title-shape">{{ staticData.s3.t1 }}</h2>
<p v-html="staticData.s3.t2"></p> <p v-html="staticData.s3.t2"></p>
</div> </div>
</section> </section>
<section class="s4"> <section class="s4">
<div class="container"> <div class="container">
<div v-for="(item , index) in staticData.s4" class="panel anim-fadeIn" :class="'p'+(index+1)"> <div v-for="(item , index) in staticData.s4" class="panel anim-fadeIn" :class="'p'+(index+1)">
<div class="row"> <div class="row">
<div class="col-12 col-lg-5 img"> <div class="col-12 col-lg-5 img">
<img :src="require('~/assets/img/about/'+ item.img)" alt=""> <img :src="require('~/assets/img/about/'+ item.img)" alt="">
</div> </div>
<div class="col-12 col-lg-7 txt"> <div class="col-12 col-lg-7 txt">
<p>{{item.title}}</p> <p>{{ item.title }}</p>
<a :href="item.link.url" class="btn btn-primary" target="_blank">{{item.link.txt}}</a> <a :href="`/standards_pdf/${item.link.url}`" download class="btn btn-primary" target="_blank">{{ item.link.txt }}</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<CustomersCommunication/> <CustomersCommunication/>
</div> </div>
</template> </template>
<script> <script>
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
import {fadeInAnimation} from '~/mixins/animations' import {fadeInAnimation} from '~/mixins/animations'
export default { export default {
data() { data() {
return { return {
history: null history: null
} }
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.about[this.$route.params.lang] return this.$store.state.staticData.about[this.$route.params.lang]
} }
}, },
mixins: [fadeInAnimation], mixins: [fadeInAnimation],
methods: { methods: {
activeHistory(item, index) { activeHistory(item, index) {
for (let i = 0; i < this.history.length; i++) { for (let i = 0; i < this.history.length; i++) {
i > index ? $(`.circle[data-c-n="${i}"]`).removeClass('active') : null i > index ? $(`.circle[data-c-n="${i}"]`).removeClass('active') : null
i > index ? $(`.line[data-l-n="${i - 1}"]`).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 ? $(`.circle[data-c-n="${i + 1}"]`).addClass('active') : null
i < index ? $(`.line[data-l-n="${i}"]`).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
}
} }
}
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> </script>
+88 -88
View File
@@ -1,96 +1,96 @@
<template> <template>
<div class="page blog-details--page"> <div class="page blog-details--page latin-digits">
<Hero :title="categoryName(post.category)"/> <Hero :title="categoryName(post.category)"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="date-category"> <div class="date-category">
<span class="category"> <span class="category">
<span>{{staticData.t1}}</span> <span>{{ staticData.t1 }}</span>
<span>{{categoryName(post.category)}}</span> <span>{{ categoryName(post.category) }}</span>
</span> </span>
<span class="date">{{jDate(post.created_at)}}</span> <span class="date">{{ jDate(post.created_at) }}</span>
</div> </div>
<div class="content" v-html="post.post_details[$route.params.lang].description"></div> <div class="ck-content" v-html="post.post_details[$route.params.lang].description"></div>
<div class="share"> <div class="share">
<p>{{staticData.t2}}</p> <p>{{ staticData.t2 }}</p>
<ul> <ul>
<li> <li>
<a target="_blank" title="Twitter" :href="'https://twitter.com/intent/tweet?url=' + domain + $route.fullPath"> <a target="_blank" title="Twitter" :href="'https://twitter.com/intent/tweet?url=' + domain + $route.fullPath">
<i class="fab fa-twitter"></i> <i class="fab fa-twitter"></i>
</a> </a>
</li> </li>
<li> <li>
<a target="_blank" title="WhatsApp" :href="'whatsapp://send?text=' + domain + $route.fullPath"> <a target="_blank" title="WhatsApp" :href="'whatsapp://send?text=' + domain + $route.fullPath">
<i class="fab fa-whatsapp"></i> <i class="fab fa-whatsapp"></i>
</a> </a>
</li> </li>
<li> <li>
<a target="_blank" title="Linked In" :href="'https://www.linkedin.com/shareArticle?mini=true&url=' + domain + $route.fullPath"> <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> <i class="fab fa-linkedin-in"></i>
</a> </a>
</li> </li>
<li> <li>
<a target="_blank" title="Facebook" :href="'https://www.facebook.com/sharer.php?u=' + domain + $route.fullPath"> <a target="_blank" title="Facebook" :href="'https://www.facebook.com/sharer.php?u=' + domain + $route.fullPath">
<i class="fab fa-facebook-f"></i> <i class="fab fa-facebook-f"></i>
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s2"> <section class="s2">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2 class="title">{{staticData.t3}}</h2> <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> <nuxt-link :to="{name: 'lang-blog',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t4 }}</nuxt-link>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<CustomersCommunication/> <CustomersCommunication/>
</div> </div>
</template> </template>
<script> <script>
import moment from "moment-jalaali" import moment from "moment-jalaali"
export default { export default {
data() { data() {
return { return {
post: null, post: null,
blogCategories: null, blogCategories: null,
domain: 'https://www.arakrail.com' domain: 'https://www.arakrail.com'
} }
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.blog_details[this.$route.params.lang] return this.$store.state.staticData.blog_details[this.$route.params.lang]
} }
}, },
methods: { methods: {
categoryName(id) { categoryName(id) {
return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name
}, },
jDate(date) { jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD') if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD')
else return date.split(' ')[0] else return date.split(' ')[0]
}, },
}, },
head() { head() {
return { return {
title: this.post.post_details[this.$route.params.lang].title title: this.post.post_details[this.$route.params.lang].title
} }
}, },
async asyncData({$axios, params}) { async asyncData({$axios, params}) {
const post = await $axios.get(`/api/public/blog/${params.post}`) const post = await $axios.get(`/api/public/blog/${params.post}`)
const blogCategories = await $axios.get(`/api/public/blogCategories`) const blogCategories = await $axios.get(`/api/public/blogCategories`)
return { return {
post: post.data, post: post.data,
blogCategories: blogCategories.data blogCategories: blogCategories.data
} }
} }
} }
</script> </script>
+119 -119
View File
@@ -1,131 +1,131 @@
<template> <template>
<div class="page blog--page"> <div class="page blog--page latin-digits">
<Hero :title="staticData.hero"/> <Hero :title="staticData.hero"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<h2 class="title">{{staticData.t1}}</h2> <h2 class="title">{{ staticData.t1 }}</h2>
<p>{{staticData.t2}}</p> <p>{{ staticData.t2 }}</p>
</div> </div>
</div> </div>
</section> </section>
<section class="s2"> <section class="s2">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div class="filters anim-fadeIn"> <div class="filters anim-fadeIn">
<h2 class="title">{{staticData.t3}}</h2> <h2 class="title">{{ staticData.t3 }}</h2>
<ul> <ul>
<li @click="filtering(false)"> <li @click="filtering(false)">
<p class="active">{{staticData.t7}}</p> <p class="active">{{ staticData.t7 }}</p>
</li> </li>
<li v-for="item in blogCategories" :key="item._id" @click="filtering(item._id)"> <li v-for="item in blogCategories" :key="item._id" @click="filtering(item._id)">
<p>{{item.blogCategory_details[$route.params.lang].name}}</p> <p>{{ item.blogCategory_details[$route.params.lang].name }}</p>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s3"> <section class="s3">
<div class="container"> <div class="container">
<div class="row posts-container" v-if="filtered_posts.length"> <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="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="panel">
<div class="imgBox imgBox-reverse"> <div class="imgBox imgBox-reverse">
<div class="img"> <div class="img">
<img :src="item.thumb" :alt="item.post_details[$route.params.lang].title"> <img :src="item.thumb" :alt="item.post_details[$route.params.lang].title">
</div> </div>
</div> </div>
<div class="txtBox"> <div class="txtBox">
<div class="date-category"> <div class="date-category">
<span class="category"> <span class="category">
<span>{{staticData.t4}}</span> <span>{{ staticData.t4 }}</span>
<span>{{categoryName(item.category)}}</span> <span>{{ categoryName(item.category) }}</span>
</span> </span>
<span class="date">{{jDate(item.created_at)}}</span> <span class="date">{{ jDate(item.created_at) }}</span>
</div> </div>
<h4>{{item.post_details[$route.params.lang].title}}</h4> <h4>{{ item.post_details[$route.params.lang].title }}</h4>
<p>{{item.post_details[$route.params.lang].short_description}}</p> <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> <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> </div>
</div> </div>
<div class="row" v-else> <div class="row" v-else>
<div class="col-12"> <div class="col-12">
<p class="no-post posts-container anim-fadeIn">{{staticData.t6}}</p> <p class="no-post posts-container anim-fadeIn">{{ staticData.t6 }}</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</div> </div>
</template> </template>
<script> <script>
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
import {fadeInAnimation} from "~/mixins/animations" import {fadeInAnimation} from "~/mixins/animations"
export default { export default {
data() { data() {
return { return {
posts: null, posts: null,
blogCategories: null, blogCategories: null,
filter: false filter: false
} }
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.blog[this.$route.params.lang] return this.$store.state.staticData.blog[this.$route.params.lang]
}, },
filtered_posts() { filtered_posts() {
if (!this.filter) return this.posts if (!this.filter) return this.posts
else return this.posts.filter(item => item.category === this.filter) else return this.posts.filter(item => item.category === this.filter)
} }
}, },
methods: { methods: {
categoryName(id) { categoryName(id) {
return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name return this.blogCategories.filter(item => item._id === id)[0].blogCategory_details[this.$route.params.lang].name
}, },
jDate(date) { jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD') if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD')
else return date.split(' ')[0] else return date.split(' ')[0]
}, },
filtering(key) { filtering(key) {
$('.blog--page .filters p').removeClass('active') $('.blog--page .filters p').removeClass('active')
$(event.target).addClass('active') $(event.target).addClass('active')
this.$gsap.timeline({ this.$gsap.timeline({
yoyo: true, yoyo: true,
repeat: 1 repeat: 1
}) })
.to($('.blog--page .posts-container'), .to($('.blog--page .posts-container'),
{ {
opacity: 0, opacity: 0,
duration: 0.3, duration: 0.3,
onComplete: () => { onComplete: () => {
this.filter = key this.filter = key
} }
}) })
} }
}, },
mixins: [fadeInAnimation], mixins: [fadeInAnimation],
head() { head() {
return { return {
title: this.staticData.hero title: this.staticData.hero
} }
}, },
async asyncData({$axios, store}) { async asyncData({$axios, store}) {
let posts = await $axios.get(`/api/public/blog`) let posts = await $axios.get(`/api/public/blog`)
const blogCategories = await $axios.get(`/api/public/blogCategories`) const blogCategories = await $axios.get(`/api/public/blogCategories`)
return { return {
posts: posts.data, posts: posts.data,
blogCategories: blogCategories.data blogCategories: blogCategories.data
} }
} }
} }
</script> </script>
+434 -189
View File
@@ -1,224 +1,469 @@
<template> <template>
<div class="page calculation--page"> <div class="page calculation--page latin-digits">
<Hero title="نرم افزار محاسبه"/> <Hero :title="staticData.hero"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<h2 class="title">وزن گریتینگ</h2> <h2 class="title">{{ staticData.app.t1 }}</h2>
<p>بدلیل این که وزن گریتینگ ها به واسطه مواردی همچون مشخصات فنی یا همان دیتیل ساخت از جمله نوع گریتینگ،جنس تسمه و اندازه چشمه ها متغیر است،بدین منظور جهت راحتی و سهولت در انجام کار شما مشتری گرامی، شرکت اراک ریل نرم افزار محاسبه وزن و میزان بار قابل تحمل را برای گریتینگ طراحی و در این صفحه قرار داده است.که با داشتن مشخصات فنی گریتینگ مورد نظر خود میتوانید وزن گریتینگ خود را همراه با گالوانیزه و یا بدون گالوانیزه محاسبه کنید.</p> <p>{{ staticData.app.t2 }}</p>
</div> </div>
</div> </div>
</section> </section>
<section class="s2"> <section class="s2">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="app m-auto" :class="app.method === 'a' ? 'col-12 col-lg-6' : 'col-12'"> <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="container-fluid">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div class="appTitle"> <div class="appTitle">
<h2 class="title">ظرفیت بارگیری گریتینگ خود را محاسبه کنید</h2> <h2 class="title">{{ staticData.app.t3 }}</h2>
</div> </div>
<div class="appMethod"> <div class="appMethod">
<span>روش محاسبه</span> <span class="txt">{{ staticData.app.t4 }}</span>
<el-radio-group v-model="app.method" style="direction: ltr"> <el-radio-group v-model="app.method" style="direction: ltr">
<el-radio-button label="b">نفر یا وسیله نقلیه</el-radio-button> <template v-if="$route.params.lang === 'fa'">
<el-radio-button label="a">وارد کردن بار</el-radio-button> <el-radio-button label="classified">{{ staticData.app.t5 }}</el-radio-button>
</el-radio-group> <el-radio-button label="custom">{{ staticData.app.t6 }}</el-radio-button>
</div> </template>
</div> <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 === 'b'"> <div class="col-12 col-lg-6 mb-5 mb-lg-0" v-if="app.method === 'classified'">
<div class="appLayout"> <div class="appLayout">
<h2 class="layoutTitle">انتخاب کلاس لودینگ</h2> <h2 class="layoutTitle">{{ staticData.app.t7 }}</h2>
<div class="class"> <div class="class">
<h4>عابر پیاده:</h4> <h4>{{ staticData.app.t8 }}</h4>
<el-radio v-model="app.class" :label="1">کلاس 1</el-radio> <el-radio v-model="app.vehicleClass" label="class1">{{ staticData.app.t9 }}</el-radio>
</div> </div>
<div class="class"> <div class="class">
<h4>وسایل نقلیه:</h4> <h4>{{ staticData.app.t10 }}</h4>
<el-radio v-model="app.class" :label="2">کلاس 2</el-radio> <el-radio v-model="app.vehicleClass" label="class2">{{ staticData.app.t11 }}</el-radio>
<el-radio v-model="app.class" :label="3">کلاس 3</el-radio> <el-radio v-model="app.vehicleClass" label="class3">{{ staticData.app.t12 }}</el-radio>
<el-radio v-model="app.class" :label="4">کلاس 4</el-radio> <el-radio v-model="app.vehicleClass" label="class4">{{ staticData.app.t13 }}</el-radio>
</div> </div>
<div class="class"> <div class="class">
<h4>لیفتراک:</h4> <h4>{{ staticData.app.t14 }}</h4>
<el-radio v-model="app.class" :label="5">FL1</el-radio> <el-radio v-model="app.vehicleClass" label="FL1">FL1</el-radio>
<el-radio v-model="app.class" :label="6">FL2</el-radio> <el-radio v-model="app.vehicleClass" label="FL2">FL2</el-radio>
<el-radio v-model="app.class" :label="7">FL3</el-radio> <el-radio v-model="app.vehicleClass" label="FL3">FL3</el-radio>
<el-radio v-model="app.class" :label="8">FL4</el-radio> <el-radio v-model="app.vehicleClass" label="FL4">FL4</el-radio>
<el-radio v-model="app.class" :label="9">FL5</el-radio> <el-radio v-model="app.vehicleClass" label="FL5">FL5</el-radio>
<el-radio v-model="app.class" :label="10">FL6</el-radio> <el-radio v-model="app.vehicleClass" label="FL6">FL6</el-radio>
</div> </div>
</div> </div>
</div> </div>
<div :class="app.method === 'a' ? 'col-12' : 'col-12 col-lg-6'"> <div :class="app.method === 'custom' ? 'col-12' : 'col-12 col-lg-6'">
<div class="appLayout"> <div class="appLayout">
<h2 class="layoutTitle">اطلاعات ورودی</h2> <h2 class="layoutTitle">{{ staticData.app.t15 }}</h2>
<el-form key="form-a"> <el-form key="form-a">
<el-form-item label="نوع گریتینگ"> <el-form-item :label="staticData.app.t16">
<el-radio-group v-model="app.type"> <el-radio-group v-model="app.gratingType">
<el-radio label="elec">الکتروفورج</el-radio> <el-radio label="forge">{{ staticData.app.t17 }}</el-radio>
<el-radio label="press">پرسی</el-radio> <el-radio label="pressured">{{ staticData.app.t18 }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="بار متمرکز (kn)"> <el-form-item :label="staticData.app.t19" v-if="app.method === 'custom'">
<el-input v-model="app.pointLoad" placeholder="وارد کنید"></el-input> <el-radio-group v-model="app.loadType">
<!-- <span>kn</span>--> <el-radio label="pointedLoad">{{ staticData.app.t20 }}</el-radio>
</el-form-item> <el-radio label="distributedLoad">{{ staticData.app.t21 }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="بار گسترده (kn/m2)"> <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.distributedLoad" placeholder="وارد کنید"></el-input> <el-input v-model="app.pointedLoadValue" :placeholder="staticData.app.enter"></el-input>
<!-- <span>kn/m2</span>--> <p class="err" v-if="validation.pointedLoadValue">{{ validation.pointedLoadValue.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item label="گام تسمه های باربر (mm)"> <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-select v-model="app.bearingBarPitch" key="bearingBarPitch_elec" v-if="app.type === 'elec'" placeholder="انتخاب کنید"> <el-form-item :class="validation.bearingBarPitch ? 'is-error' : null" :label="staticData.app.t24">
<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-select v-model="app.bearingBarPitch" key="bearingBarPitch_forge" v-if="app.gratingType === 'forge'"
<el-option :placeholder="staticData.app.select">
v-for="item in bearingBarPitch_press" <el-option
:key="item" v-for="item in calculationValues.bearingBarPitch_forge"
:label="item" :key="item"
:value="item"> :label="item"
</el-option> :value="item">
</el-select> </el-option>
</el-select>
<!-- <span>mm</span>--> <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>
</el-form-item> <p class="err" v-if="validation.bearingBarPitch">{{ validation.bearingBarPitch.msg }}</p>
<el-form-item label="گام تسمه های رابط (mm)">
<el-select v-model="app.crossBarPitCh" key="bearingBarPitch_elec" v-if="app.type === 'elec'" placeholder="انتخاب کنید"> </el-form-item>
<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-form-item :class="validation.crossBarPitch ? 'is-error' : null" :label="staticData.app.t25">
<el-option
v-for="item in crossBarPitCh_press"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
<!-- <span>mm</span>--> <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-form-item> <el-select v-model="app.crossBarPitch" key="crossBarPitch_pressured" v-if="app.gratingType === 'pressured'" :placeholder="staticData.app.select">
<el-form-item label="دهنه باربر (mm)"> <el-option
<el-input v-model="app.clearSpan" placeholder="وارد کنید"></el-input> v-for="item in calculationValues.crossBarPitch_pressured"
<!-- <span>mm</span>--> :key="item"
</el-form-item> :label="item"
:value="item">
</el-option>
</el-select>
<el-form-item label="ضخامت تسمه های باربر (mm)"> <p class="err" v-if="validation.crossBarPitch">{{ validation.crossBarPitch.msg }}</p>
<el-input v-model="app.bearingBarThickness" placeholder="وارد کنید"></el-input>
<!-- <span>mm</span>-->
</el-form-item>
<el-form-item label="ارتفاع تسمه های باربر (mm)"> </el-form-item>
<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> <el-form-item :class="validation.clearSpan ? 'is-error' : null" :label="staticData.app.t26">
</div> <el-input v-model="app.clearSpan" :placeholder="staticData.app.enter"></el-input>
</div> <p class="err" v-if="validation.clearSpan">{{ validation.clearSpan.msg }}</p>
</el-form-item>
</div> <el-form-item :class="validation.bearingBarThickness ? 'is-error' : null" :label="staticData.app.t27">
</div> <el-input v-model="app.bearingBarThickness" :placeholder="staticData.app.enter"></el-input>
</section> <p class="err" v-if="validation.bearingBarThickness">{{ validation.bearingBarThickness.msg }}</p>
</div> </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> </template>
<script> <script>
import moment from 'moment-jalaali' import {fadeInAnimation} from '~/mixins/animations'
import {fadeInAnimation} from '~/mixins/animations'
export default { export default {
data() { data() {
return { return {
history: null, app: {
app: { method: 'custom',
method: 'a', gratingType: 'forge',
type: 'elec', loadType: 'pointedLoad',
class: '', vehicleClass: 'class1',
pointLoad: '', pointedLoadValue: '',
distributedLoad: '', distributedLoadValue: '',
bearingBarPitch: '', bearingBarPitch: '',
crossBarPitCh: '', crossBarPitch: '',
clearSpan: '', clearSpan: '',
bearingBarThickness: '', bearingBarThickness: '',
bearingBarHeight: '', bearingBarHeight: '',
locale: this.$route.params.lang 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]
}
}, },
computed: { calculationValues: null,
staticData() { relativeValues: null,
return this.$store.state.staticData.calculation[this.$route.params.lang] validation: {},
} waiting: false,
}, appResult: null
mixins: [fadeInAnimation], }
methods: {}, },
head() { computed: {
return { staticData() {
htmlAttrs: { return this.$store.state.staticData.calculation[this.$route.params.lang]
title: this.staticData.hero },
} 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> </script>
<style lang="scss"> <style lang="scss">
.el-popper .popper__arrow { .el-popper .popper__arrow {
border-width: 0; border-width: 0;
filter: none; filter: none;
left: 35px; left: 35px;
&:lang(fa) { &:lang(fa) {
left: auto; left: auto;
right: 35px; right: 35px;
} }
} }
</style> </style>
+199 -198
View File
@@ -1,209 +1,210 @@
<template> <template>
<div class="page contact--page"> <div class="page contact--page">
<Hero :title="staticData.hero"/> <Hero :title="staticData.hero"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="row"> <div class="row">
<div class="col-12 p1"> <div class="col-12 p1">
<h2 class="title">{{staticData.t1}}</h2> <h2 class="title">{{ staticData.t1 }}</h2>
<p>{{staticData.t2}}</p> <!-- <p>{{staticData.t2}}</p>-->
</div> </div>
<div class="col-12 p2"> <div class="col-12 p2">
<ul> <ul>
<li> <li>
<i class="fas fa-map-marker-alt"></i> <i class="fas fa-map-marker-alt"></i>
<span>{{staticData.t3}}</span> <span>{{ $store.state.global.address[$route.params.lang] }}</span>
</li> </li>
<li> <li>
<i class="fas fa-phone"></i> <i class="fas fa-phone"></i>
<a href="tel: +988634132704">Tell: +98 86 3 413 2704 - 7</a> <a :href="'tel:' + $store.state.global.tell">
- <span>{{ staticData.t15 }}</span>
<a href="tel: +988634132703">Fax: +98 86 3 413 27 03</a> <b class="phone-number">{{ $store.state.global.tell_view }}</b>
</li> </a>
<li> -
<i class="fas fa-envelope"></i> <a :href="'tel:' + $store.state.global.fax">
<a href="mailto: info@arakrail.com">info@arakrail.com</a> <span>{{ staticData.t16 }}</span>
</li> <b class="phone-number">{{ $store.state.global.fax_view }}</b>
</ul> </a>
</div> </li>
<div class="col-12 p3"> <li>
<hr> <i class="fas fa-envelope"></i>
<b>{{staticData.t4}}</b> <a :href="'mailto:' + $store.state.global.email">{{ $store.state.global.email }}</a>
<p>{{staticData.t5}}</p> </li>
<ul> </ul>
<li> </div>
<a href="" target="_blank"> <div class="col-12 p3">
<i class="fab fa-facebook-f"></i> <hr>
</a> <b>{{ staticData.t4 }}</b>
</li> <p>{{ staticData.t5 }}</p>
<li> <ul>
<a href="" target="_blank"> <li>
<i class="fab fa-twitter"></i> <a :href="$store.state.global.instagram_url" target="_blank">
</a> <i class="fab fa-instagram"></i>
</li> </a>
<li> </li>
<a href="" target="_blank"> <li>
<i class="fab fa-telegram-plane"></i> <a :href="$store.state.global.linkedin_url" target="_blank">
</a> <i class="fab fa-linkedin-in"></i>
</li> </a>
</ul> </li>
</div> </ul>
<div class="col-12 p4"> </div>
<div class="mapouter"> <div class="col-12 p4">
<div class="gmap_canvas"> <div class="mapouter">
<iframe id="gmap_canvas" <div class="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" <iframe id="gmap_canvas"
frameborder="0" scrolling="no" marginheight="0" marginwidth="0"> 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"
</iframe> frameborder="0" scrolling="no" marginheight="0" marginwidth="0">
</div> </iframe>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
<section class="s2"> </section>
<div class="container"> <section class="s2">
<div class="panel"> <div class="container">
<div class="row"> <div class="panel">
<div class="col-12"> <div class="row">
<h2>{{staticData.t6}}</h2> <div class="col-12">
<form class="form" @submit.prevent="upload"> <h2>{{ staticData.t6 }}</h2>
<div class="row"> <form class="form" @submit.prevent="upload">
<div class="col-12"> <div class="row">
<div class="formRow center-align" :class="validation.reason ? 'err' : null"> <div class="col-12">
<select name="reason" v-model="formData.reason"> <div class="formRow center-align" :class="validation.reason ? 'err' : null">
<option disabled selected :value="false">{{staticData.t7}}</option> <select name="reason" v-model="formData.reason">
<option v-for="item in reasons" :key="item._id" :value="item.reason_details.fa.reason">{{item.reason_details[$route.params.lang].reason}}</option> <option disabled selected :value="false">{{ staticData.t7 }}</option>
</select> <option v-for="item in reasons" :key="item._id" :value="item.reason_details.fa.reason">{{ item.reason_details[$route.params.lang].reason }}</option>
<p v-if="validation.reason">{{validation.reason.msg}}</p> </select>
</div> <p v-if="validation.reason">{{ validation.reason.msg }}</p>
</div> </div>
<div class="col-12 col-lg-6"> </div>
<div class="formRow" :class="validation.first_name ? 'err' : null"> <div class="col-12 col-lg-6">
<input type="text" :placeholder="staticData.t8" name="first_name" v-model="formData.first_name"> <div class="formRow" :class="validation.first_name ? 'err' : null">
<p v-if="validation.first_name">{{validation.first_name.msg}}</p> <input type="text" :placeholder="staticData.t8" name="first_name" v-model="formData.first_name">
</div> <p v-if="validation.first_name">{{ validation.first_name.msg }}</p>
</div> </div>
<div class="col-12 col-lg-6"> </div>
<div class="formRow" :class="validation.last_name ? 'err' : null"> <div class="col-12 col-lg-6">
<input type="text" :placeholder="staticData.t9" name="last_name" v-model="formData.last_name"> <div class="formRow" :class="validation.last_name ? 'err' : null">
<p v-if="validation.last_name">{{validation.last_name.msg}}</p> <input type="text" :placeholder="staticData.t9" name="last_name" v-model="formData.last_name">
</div> <p v-if="validation.last_name">{{ validation.last_name.msg }}</p>
</div> </div>
<div class="col-12 col-lg-6"> </div>
<div class="formRow" :class="validation.phone_number ? 'err' : null"> <div class="col-12 col-lg-6">
<input type="text" :placeholder="staticData.t10" name="phone_number" v-model="formData.phone_number"> <div class="formRow" :class="validation.phone_number ? 'err' : null">
<p v-if="validation.phone_number">{{validation.phone_number.msg}}</p> <input type="text" :placeholder="staticData.t10" name="phone_number" v-model="formData.phone_number">
</div> <p v-if="validation.phone_number">{{ validation.phone_number.msg }}</p>
</div> </div>
<div class="col-12 col-lg-6"> </div>
<div class="formRow" :class="validation.email ? 'err' : null"> <div class="col-12 col-lg-6">
<input type="text" :placeholder="staticData.t11" name="email" v-model="formData.email"> <div class="formRow" :class="validation.email ? 'err' : null">
<p v-if="validation.email">{{validation.email.msg}}</p> <input type="text" :placeholder="staticData.t11" name="email" v-model="formData.email">
</div> <p v-if="validation.email">{{ validation.email.msg }}</p>
</div> </div>
<div class="col-12"> </div>
<div class="formRow" :class="validation.message ? 'err' : null"> <div class="col-12">
<textarea :placeholder="staticData.t12" name="message" v-model="formData.message"></textarea> <div class="formRow" :class="validation.message ? 'err' : null">
<p v-if="validation.message">{{validation.message.msg}}</p> <textarea :placeholder="staticData.t12" name="message" v-model="formData.message"></textarea>
</div> <p v-if="validation.message">{{ validation.message.msg }}</p>
</div> </div>
<div class="col-12"> </div>
<div class="formRow center-align"> <div class="col-12">
<button type="submit" class="btn btn-primary-fill">{{staticData.t13}}</button> <div class="formRow center-align">
</div> <button type="submit" class="btn btn-primary-fill">{{ staticData.t13 }}</button>
</div> </div>
</div> </div>
</form> </div>
</div> </form>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
</div> </section>
</div>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
formData: { formData: {
reason: false, reason: false,
first_name: '', first_name: '',
last_name: '', last_name: '',
phone_number: '', phone_number: '',
email: '', email: '',
message: '', message: '',
locale: this.$route.params.lang locale: this.$route.params.lang
},
reasons: null,
validation: {}
}
}, },
computed: { reasons: null,
staticData() { validation: {}
return this.$store.state.staticData.contact[this.$route.params.lang] }
} },
}, computed: {
methods: { staticData() {
upload() { return this.$store.state.staticData.contact[this.$route.params.lang]
this.validation = {} }
const data = this.formData },
this.$axios.post(`/api/public/contact`, data) methods: {
.then(res => { upload() {
this.$message({ this.validation = {}
message: this.staticData.t14, const data = this.formData
type: 'success' this.$axios.post(`/api/public/contact`, data)
}) .then(res => {
this.formData = { this.$message({
reason: false, message: this.staticData.t14,
first_name: '', type: 'success'
last_name: '', })
phone_number: '', this.formData = {
email: '', reason: false,
message: '', first_name: '',
locale: this.$route.params.lang last_name: '',
} phone_number: '',
}) email: '',
.catch(err => { message: '',
if (err.response.status === 422) this.validation = err.response.data.validation locale: this.$route.params.lang
else console.log(err.response.data.message) }
}) })
} .catch(err => {
}, if (err.response.status === 422) this.validation = err.response.data.validation
head() { else console.log(err.response.data.message)
return { })
title: this.staticData.hero }
} },
}, head() {
async asyncData({$axios}) { return {
const reasons = await $axios.get(`/api/public/contact/reason`) title: this.staticData.hero
return { }
reasons: reasons.data },
} async asyncData({$axios}) {
} const reasons = await $axios.get(`/api/public/contact/reason`)
} return {
reasons: reasons.data
}
}
}
</script> </script>
<style> <style>
.mapouter{ .mapouter{
position: relative; position: relative;
text-align: right; text-align: right;
height: 500px; height: 500px;
width: 100%; width: 100%;
} }
.gmap_canvas{ .gmap_canvas{
overflow: hidden; overflow: hidden;
background: none !important; background: none !important;
height: 500px; height: 500px;
width: 100%; width: 100%;
} }
#gmap_canvas{ #gmap_canvas{
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
</style> </style>
+213 -214
View File
@@ -1,232 +1,231 @@
<template> <template>
<div class="page home--page"> <div class="page home--page">
<div class="slider-container"> <div class="slider-container">
<div id="slider" class="anim-parallax-hero"> <div id="slider" class="anim-parallax-hero">
<div class="hero clearfix" v-for="item in slider" :key="item._id"> <div class="hero clearfix" v-for="item in slider" :key="item._id">
<div class="bg" :style="{backgroundImage: `url(${item.image})`}"></div> <div class="bg" :style="{backgroundImage: `url(${item.image})`}"></div>
<div class="txt--home"> <div class="txt--home">
<h1>{{item.slider_details[$route.params.lang].title}}</h1> <h1>{{ item.slider_details[$route.params.lang].title }}</h1>
<p>{{item.slider_details[$route.params.lang].caption}}</p> <p>{{ item.slider_details[$route.params.lang].caption }}</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<section class="s1"> <section class="s1">
<div class="go-down-btn" @click="scrollDown"> <div class="go-down-btn" @click="scrollDown">
<em class="fa fa-angle-double-down"></em> <em class="fa fa-angle-double-down"></em>
</div> </div>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 col-md-6 title-side"> <div class="col-12 col-md-6 title-side">
<h2 class="title title-shape">{{staticData.s1.title}}</h2> <h2 class="title title-shape">{{ staticData.s1.title }}</h2>
</div> </div>
<div class="col-12 col-md-6 caption-side"> <div class="col-12 col-md-6 caption-side">
<p>{{staticData.s1.caption}}</p> <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> <nuxt-link :to="{name: 'lang-about',params:{lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s1.link }}</nuxt-link>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s2"> <section class="s2">
<img src="~/assets/img/home/hp-s1-i2.jpg" alt="" class="section-bg anim-parallax"> <img src="~/assets/img/home/hp-s1-i2.jpg" alt="" class="section-bg anim-parallax">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2 class="title title-shape-center">{{staticData.s1_2.t1}}</h2> <h2 class="title title-shape-center">{{ staticData.s1_2.t1 }}</h2>
</div> </div>
<div class="col-12"> <div class="col-12">
<p>{{staticData.s1_2.t2}}</p> <p>{{ staticData.s1_2.t2 }}</p>
<p>{{staticData.s1_2.t3}}</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> <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> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s3"> <section class="s3">
<img src="~/assets/img/home/hp-s2-i1.jpg" alt="" class="section-bg anim-parallax"> <img src="~/assets/img/home/hp-s2-i1.jpg" alt="" class="section-bg anim-parallax">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="container-fluid"> <div class="container-fluid">
<div class="parts p1"> <div class="parts p1">
<h2 class="title title-shape-center">{{staticData.s2.t1}}</h2> <h2 class="title title-shape-center">{{ staticData.s2.t1 }}</h2>
<div> <div>
<p>{{staticData.s2.t2}}</p> <p>{{ staticData.s2.t2 }}</p>
</div> </div>
</div> </div>
<div class="parts p2 row"> <div class="parts p2 row">
<div class="col-12 col-lg-6 order-1 order-lg-0"> <div class="col-12 col-lg-6 order-1 order-lg-0">
<div class="txtBox"> <div class="txtBox">
<h2 class="title title-subtitle">{{staticData.s2.t5}}</h2> <h2 class="title title-subtitle">{{ staticData.s2.t5 }}</h2>
<p>{{staticData.s2.t6}}</p> <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> <nuxt-link :to="{name: 'lang-services',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s2.link1 }}</nuxt-link>
</div> </div>
</div> </div>
<div class="col-12 col-lg-6 order-0 order-lg-1 mb-5 mb-lg-0"> <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="imgBox imgBox-shape anim-fadeIn">
<div class="img"> <div class="img">
<img src="~/assets/img/home/hp-s2-i2.jpg" alt=""> <img src="~/assets/img/home/hp-s2-i2.jpg" alt="">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="parts p3 row"> <div class="parts p3 row">
<div class="col-12 col-lg-6 mb-5 mb-lg-0"> <div class="col-12 col-lg-6 mb-5 mb-lg-0">
<div class="imgBox imgBox-reverse imgBox-shape-reverse anim-fadeIn"> <div class="imgBox imgBox-reverse imgBox-shape-reverse anim-fadeIn">
<div class="img"> <div class="img">
<img src="~/assets/img/home/hp-s2-i3.jpg" alt=""> <img src="~/assets/img/home/hp-s2-i3.jpg" alt="">
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 col-lg-6"> <div class="col-12 col-lg-6">
<div class="txtBox"> <div class="txtBox">
<h2 class="title title-subtitle">{{staticData.s2.t3}}</h2> <h2 class="title title-subtitle">{{ staticData.s2.t3 }}</h2>
<p>{{staticData.s2.t4}}</p> <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> <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>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s4"> <section class="s4">
<img src="~/assets/img/home/hp-s3-i1.jpg" alt="" class="section-bg anim-parallax"> <img src="~/assets/img/home/hp-s3-i1.jpg" alt="" class="section-bg anim-parallax">
<div class="container clearfix"> <div class="container clearfix">
<div class="panel"> <div class="panel">
<div class="parts p1"> <div class="parts p1">
<h2 class="title title-shape-center">{{staticData.s3.t1}}</h2> <h2 class="title title-shape-center">{{ staticData.s3.t1 }}</h2>
<div class="col-12"> <div class="col-12">
<p>{{staticData.s3.t2}}</p> <p>{{ staticData.s3.t2 }}</p>
</div> </div>
</div> </div>
</div> </div>
<div class="products"> <div class="products">
<div class="parts p2 row"> <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"> <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"> <nuxt-link :to="{name: 'lang-products-product',params: {lang: $route.params.lang,product: item._id}}" class="product">
<div class="imgBox"> <div class="imgBox">
<img :src="item.cover" :alt="item.product_details[$route.params.lang].name"> <img :src="item.thumb" :alt="item.product_details[$route.params.lang].name">
</div> </div>
<p>{{item.product_details[$route.params.lang].name}}</p> <p>{{ item.product_details[$route.params.lang].name }}</p>
</nuxt-link> </nuxt-link>
</div> </div>
<div class="col-12"> <div class="col-12">
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.s3.link}}</nuxt-link> <nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.s3.link }}</nuxt-link>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s5"> <section class="s5">
<img src="~/assets/img/home/hp-s4-i1.jpg" alt="" class="section-bg"> <img src="~/assets/img/home/hp-s4-i1.jpg" alt="" class="section-bg">
<div class="txt anim-parallax"> <div class="txt anim-parallax">
<h2 class="title title-shape">{{staticData.s4.t1}} <span>{{staticData.s4.t2}}</span></h2> <h2 class="title title-shape">{{ staticData.s4.t1 }} <span>{{ staticData.s4.t2 }}</span></h2>
<p>{{staticData.s4.t3}}</p> <p>{{ staticData.s4.t3 }}</p>
<a :href="catalog.file" target="_blank" class="btn btn-reverse-fill">{{staticData.s4.link}}</a> <a v-if="catalog && catalog.file" :href="catalog.file[$route.params.lang]" target="_blank" class="btn btn-reverse-fill">{{ staticData.s4.link }}</a>
</div> </div>
</section> </section>
<CustomersCommunication/> <CustomersCommunication/>
<section class="s6"> <section class="s6">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-2 d-none d-lg-block"></div> <div class="col-2 d-none d-lg-block"></div>
<div class="col-12 col-lg-6"> <div class="col-12 col-lg-6">
<h2 class="title title-shape">{{staticData.s6.t1}}</h2> <h2 class="title title-shape">{{ staticData.s6.t1 }}</h2>
<p>{{staticData.s6.t2}}</p> <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>--> <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>
<a @click.prevent="notAvailable" :href="calc_app_link" target="_blank" class="btn btn-primary-fill">{{staticData.s6.link2}}</a> </div>
</div> <div class="col-2 img-side d-none d-lg-block">
<div class="col-2 img-side d-none d-lg-block"> <img src="~/assets/img/home/hp-s6-i1.png" class="anim-fadeIn" alt="">
<img src="~/assets/img/home/hp-s6-i1.png" class="anim-fadeIn" alt=""> </div>
</div> </div>
</div> </div>
</div> </section>
</section> </div>
</div>
</template> </template>
<script> <script>
if (process.client) require('slick-carousel') if (process.client) require('slick-carousel')
import {fadeInAnimation, parallaxAnimation, parallaxAnimation_hero} from '~/mixins/animations' import {fadeInAnimation, parallaxAnimation, parallaxAnimation_hero} from '~/mixins/animations'
export default { export default {
data() { data() {
return { return {
slider: null, slider: null,
products: null, favoriteProducts: null,
catalog: null, catalog: null,
calc_app_link: this.$store.state.staticData.calc_app_link, calc_app_link: this.$store.state.staticData.calc_app_link,
validation: [] validation: []
} }
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.homePage[this.$route.params.lang] return this.$store.state.staticData.homePage[this.$route.params.lang]
} }
}, },
methods: { methods: {
scrollDown() { scrollDown() {
this.$gsap.to(window, {scrollTo: {y: $('.home--page .s1'), offsetY: 90}, duration: 0.9, ease: 'power4.inOut'}) this.$gsap.to(window, {scrollTo: {y: $('.home--page .s1'), offsetY: 90}, duration: 0.9, ease: 'power4.inOut'})
}, },
notAvailable() { notAvailable() {
this.$alert(this.$route.params.lang === 'fa' ? 'این بخش فعلا در دسترس نیست' : 'This section is currently unavailable', '', { this.$alert(this.$route.params.lang === 'fa' ? 'این بخش فعلا در دسترس نیست' : 'This section is currently unavailable', '', {
confirmButtonText: 'OK', confirmButtonText: 'OK',
}) })
} }
}, },
mixins: [fadeInAnimation, parallaxAnimation, parallaxAnimation_hero], mixins: [fadeInAnimation, parallaxAnimation, parallaxAnimation_hero],
mounted() { mounted() {
/////////////////////////////////////// carousel /////////////////////////////////////// carousel
$('#slider').slick({ $('#slider').slick({
slidesToShow: 1, slidesToShow: 1,
rtl: this.$route.params.lang === 'fa', rtl: this.$route.params.lang === 'fa',
dots: true, dots: true,
autoplay: true, autoplay: true,
autoplaySpeed: 6000, autoplaySpeed: 6000,
responsive: [ responsive: [
{ {
breakpoint: 768, breakpoint: 768,
settings: { settings: {
arrows: false arrows: false
} }
} }
] ]
}) })
}, },
head() { head() {
return { return {
title: this.staticData.title title: this.staticData.title
} }
}, },
async asyncData({$axios}) { async asyncData({$axios}) {
const slider = await $axios.get('/api/public/slider') const slider = await $axios.get('/api/public/slider')
const products = await $axios.get(`/api/public/products`) const favoriteProducts = await $axios.get(`/api/public/favoriteProducts`)
const catalog = await $axios.get('/api/public/catalog') const catalog = await $axios.get('/api/public/catalog')
return { return {
slider: slider.data, slider: slider.data,
products: products.data, favoriteProducts: favoriteProducts.data,
catalog: catalog.data catalog: catalog.data
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.footer{ .footer{
background: #F0F0F0 !important; background: #F0F0F0 !important;
} }
</style> </style>
+169 -167
View File
@@ -1,183 +1,185 @@
<template> <template>
<div class="page product-details--page"> <div class="page product-details--page latin-digits">
<Hero :title="staticData.hero"/> <Hero :title="staticData.hero"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<h2 class="title">{{productDetails.page_title}}</h2> <h2 class="title">{{ productDetails.page_title }}</h2>
<p>{{productDetails.page_description}}</p> <p>{{ productDetails.page_description }}</p>
<div class="image-preview"> <div class="image-preview">
<img :src="product.cover" class="anim-fadeIn" ref="preview" :alt="productDetails.name"> <img :src="product.cover" class="anim-fadeIn" ref="preview" :alt="productDetails.name">
</div> <div class="images-carousel anim-fadeIn" v-if="product.images.length">
</div> <div id="images">
<div class="images-carousel anim-fadeIn"> <div class="imgBox">
<div id="images"> <img class="selected" :src="product.cover" :alt="productDetails.name" @click="view(product.cover)">
<div class="imgBox"> </div>
<img :src="product.cover" :alt="productDetails.name" @click="view(product.cover)"> <div class="imgBox" v-for="item in product.images" :key="item._id">
</div> <img :src="item.image" :alt="productDetails.name" @click="view(item.image)">
<div class="imgBox" v-for="item in product.images" :key="item._id"> </div>
<img :src="item.image" :alt="productDetails.name" @click="view(item.image)"> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</section>
<section class="s2" v-if="product.more_section"> </div>
<div class="container"> </section>
<div class="panel">
<div class="parts p1">
<h2 class="title title-shape-center">{{staticData.t1}}</h2>
</div>
<!-- image left --> <section class="s2" v-if="product.more_section">
<div class="parts row align-items-center"> <div class="container">
<div class="col-6"> <div class="panel">
<h2 class="title title-subtitle">{{productDetails.more_title1}}</h2> <div class="parts p1">
<p>{{productDetails.more_description1}}</p> <h2 class="title title-shape-center">{{ staticData.t1 }}</h2>
</div> </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 --> <!-- image left -->
<div class="parts row align-items-center"> <div class="parts row align-items-center">
<div class="col-6"> <div class="col-6">
<div class="imgBox imgBox-reverse imgBox-shape-reverse anim-fadeIn"> <h2 class="title title-subtitle">{{ productDetails.more_title1 }}</h2>
<img :src="product.more_section_image2" :alt="productDetails.more_title2"> <p>{{ productDetails.more_description1 }}</p>
</div> </div>
</div> <div class="col-6">
<div class="col-6"> <div class="imgBox imgBox-shape anim-fadeIn">
<h2 class="title title-subtitle">{{productDetails.more_title2}}</h2> <img :src="product.more_section_image1" :alt="productDetails.more_title1">
<p>{{productDetails.more_description2}}</p> </div>
</div> </div>
</div> </div>
</div> <!-- image right -->
</div> <div class="parts row align-items-center">
</section> <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>
<section class="s3" </div>
v-if="!product.render_image1.includes('undefined') || </div>
!product.render_image2.includes('undefined') || </section>
<section class="s3"
v-if="product.render_image1 ||
product.render_image2 ||
product.download_section"> product.download_section">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="parts p1" v-if="!product.render_image1.includes('undefined') || !product.render_image1.includes('undefined')"> <div class="parts p1" v-if="product.render_image1 || product.render_image1">
<h2 class="title">{{staticData.t2}}</h2> <h2 class="title">{{ staticData.t2 }}</h2>
<p>{{staticData.t3}}</p> <p>{{ staticData.t3 }}</p>
</div> </div>
<div class="row parts p2" v-if="!product.render_image1.includes('undefined') || !product.render_image2.includes('undefined')"> <div class="row parts p2" v-if="product.render_image1 || product.render_image2">
<div class="col-12 col-sm-6 mb-5"> <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')"> <img :src="product.render_image1" class="anim-fadeIn" :alt="productDetails.name" v-if="product.render_image1">
<p v-if="!product.render_image1.includes('undefined')">{{productDetails.render_caption1}}</p> <p v-if="product.render_image1">{{ productDetails.render_caption1 }}</p>
</div> </div>
<div class="col-12 col-sm-6 mb-5"> <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')"> <img :src="product.render_image2" class="anim-fadeIn" :alt="productDetails.name" v-if="product.render_image2">
<p v-if="!product.render_image2.includes('undefined')">{{productDetails.render_caption2}}</p> <p v-if="product.render_image2">{{ productDetails.render_caption2 }}</p>
</div> </div>
<div class="col-12 mb-5"> </div>
<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="row parts p3" v-if="productDetails.chart_title">
<div class="col-12"> <div class="col-12">
<h2 class="title">{{productDetails.chart_title}}</h2> <h2 class="title">{{ productDetails.chart_title }}</h2>
<p>{{productDetails.chart_description}}</p> <p>{{ productDetails.chart_description }}</p>
</div> </div>
</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="row parts p4" v-if="product.download_section">
<div class="col-12"> <div class="col-12">
<h2>{{staticData.t4}}</h2> <h2>{{ staticData.t4 }}</h2>
<div class="files"> <div class="files">
<div class="file anim-fadeIn" v-for="item in product.pdf_files" :key="item._id"> <div class="file anim-fadeIn" v-for="item in product.pdf_files" :key="item._id">
<pdf-icon/> <pdf-icon/>
<p>{{item.pdf_details[$route.params.lang].name}}</p> <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> <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>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s4"> <section class="s4">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.t6}}</nuxt-link> <nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t6 }}</nuxt-link>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</div> </div>
</template> </template>
<script> <script>
if (process.client) require('slick-carousel') if (process.client) require('slick-carousel')
import {fadeInAnimation} from "~/mixins/animations" import {fadeInAnimation} from "~/mixins/animations"
export default { export default {
data() { data() {
return { return {
product: null product: null
} }
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.products_details[this.$route.params.lang] return this.$store.state.staticData.products_details[this.$route.params.lang]
}, },
productDetails() { productDetails() {
return this.product.product_details[this.$route.params.lang] return this.product.product_details[this.$route.params.lang]
} }
}, },
methods: { methods: {
view(image) { view(image) {
// console.log(image) this.$refs.preview.src = image
this.$refs.preview.src = image $('.product-details--page #images img').removeClass('selected')
} $(event.target).addClass('selected')
}, }
mixins: [fadeInAnimation], },
mounted() { mixins: [fadeInAnimation],
$('#images').slick({ mounted() {
slidesToShow: 4, $('#images').slick({
rtl: this.$route.params.lang === 'fa', slidesToShow: 4,
infinite: false, rtl: this.$route.params.lang === 'fa',
responsive: [ infinite: false,
{ responsive: [
breakpoint: 768, {
settings: { breakpoint: 768,
slidesToShow: 3 settings: {
} slidesToShow: 3
}, }
{ },
breakpoint: 575, {
settings: { breakpoint: 575,
slidesToShow: 2 settings: {
} slidesToShow: 2
} }
] }
}) ]
}, })
head() { },
return { head() {
title: this.product.product_details[this.$route.params.lang].name 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}`) async asyncData({$axios, params}) {
let productCategories = await $axios.get(`/api/public/productCategories`) let product = await $axios.get(`/api/public/product/${params.product}`)
return { let productCategories = await $axios.get(`/api/public/productCategories`)
product: product.data, return {
productCategories: productCategories.data product: product.data,
} productCategories: productCategories.data
} }
} }
}
</script> </script>
+111 -111
View File
@@ -1,121 +1,121 @@
<template> <template>
<div class="page products--page"> <div class="page products--page latin-digits">
<Hero :title="staticData.hero"/> <Hero :title="staticData.hero"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<h2 class="title">{{staticData.s1.t1}}</h2> <h2 class="title">{{ staticData.s1.t1 }}</h2>
<p>{{staticData.s1.t2}}</p> <p>{{ staticData.s1.t2 }}</p>
</div> </div>
</div> </div>
</section> </section>
<section class="s2"> <section class="s2">
<div class="container"> <div class="container">
<div class="filters anim-fadeIn"> <div class="filters anim-fadeIn">
<h2 class="title title-subtitle">{{staticData.s2.t1}}</h2> <h2 class="title title-subtitle">{{ staticData.s2.t1 }}</h2>
<ul> <ul>
<li @click="filtering(false)"> <li @click="filtering(false)">
<p class="active">{{staticData.s2.t3}}</p> <p class="active">{{ staticData.s2.t3 }}</p>
</li> </li>
<li <li
v-for="item in productCategories" v-for="item in productCategories"
:key="item._id" :key="item._id"
@click="filtering(item._id)"> @click="filtering(item._id)">
<p>{{item.category_details[$route.params.lang].name}}</p> <p>{{ item.category_details[$route.params.lang].name }}</p>
</li> </li>
</ul> </ul>
</div> </div>
<div class="row products-container" v-if="filtered_products.length"> <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"> <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"> <nuxt-link :to="{name: 'lang-products-product',params: {lang: $route.params.lang,product: item._id}}" class="product">
<div class="imgBox"> <div class="imgBox">
<img :src="item.cover" :alt="item.product_details[$route.params.lang].name"> <img :src="item.thumb" :alt="item.product_details[$route.params.lang].name">
</div> </div>
<h4>{{item.product_details[$route.params.lang].name}}</h4> <h4>{{ item.product_details[$route.params.lang].name }}</h4>
<p>{{item.product_details[$route.params.lang].short_description}}</p> <p>{{ item.product_details[$route.params.lang].short_description }}</p>
</nuxt-link> </nuxt-link>
</div> </div>
</div> </div>
<div class="row" v-else> <div class="row" v-else>
<div class="col-12 products-container"> <div class="col-12 products-container">
<p class="no-product anim-fadeIn">{{staticData.s2.t2}}</p> <p class="no-product anim-fadeIn">{{ staticData.s2.t2 }}</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s3"> <section class="s3">
<div class="container"> <div class="container">
<div class="panel anim-fadeIn"> <div class="panel anim-fadeIn">
<h2 class="title title-shape-center"> <h2 class="title title-shape-center">
{{staticData.s3.t1}} {{ staticData.s3.t1 }}
<span class="subtitle">{{staticData.s3.t2}}</span> <span class="subtitle">{{ staticData.s3.t2 }}</span>
</h2> </h2>
<p>{{staticData.s3.t3}}</p> <p>{{ staticData.s3.t3 }}</p>
<a :href="catalog.file" target="_blank" class="btn btn-reverse-fill">{{staticData.s3.t4}}</a> <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>
</div> </div>
</section> </section>
</div> </div>
</template> </template>
<script> <script>
import {fadeInAnimation} from "~/mixins/animations" import {fadeInAnimation} from "~/mixins/animations"
export default { export default {
data() { data() {
return { return {
products: null, products: null,
productCategories: null, productCategories: null,
catalog: null, catalog: null,
filter: false filter: false
} }
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.products[this.$route.params.lang] return this.$store.state.staticData.products[this.$route.params.lang]
}, },
filtered_products() { filtered_products() {
if (!this.filter) return this.products if (!this.filter) return this.products
else return this.products.filter(item => item.category === this.filter) else return this.products.filter(item => item.category === this.filter)
} }
}, },
methods: { methods: {
filtering(key) { filtering(key) {
$('.products--page .filters p').removeClass('active') $('.products--page .filters p').removeClass('active')
$(event.target).addClass('active') $(event.target).addClass('active')
this.$gsap.timeline({ this.$gsap.timeline({
yoyo: true, yoyo: true,
repeat: 1 repeat: 1
}) })
.to($('.products--page .products-container'), .to($('.products--page .products-container'),
{ {
opacity: 0, opacity: 0,
duration: 0.3, duration: 0.3,
onComplete: () => { onComplete: () => {
this.filter = key this.filter = key
} }
}) })
} }
}, },
mixins: [fadeInAnimation], mixins: [fadeInAnimation],
head() { head() {
return { return {
title: this.staticData.hero title: this.staticData.hero
} }
}, },
async asyncData({$axios, store}) { async asyncData({$axios, store}) {
const products = await $axios.get(`/api/public/products`) const products = await $axios.get(`/api/public/products`)
const productCategories = await $axios.get(`/api/public/productCategories`) const productCategories = await $axios.get(`/api/public/productCategories`)
const catalog = await $axios.get('/api/public/catalog') const catalog = await $axios.get('/api/public/catalog')
return { return {
products: products.data, products: products.data,
productCategories: productCategories.data, productCategories: productCategories.data,
catalog: catalog.data catalog: catalog.data
} }
} }
} }
</script> </script>
+109 -109
View File
@@ -1,117 +1,117 @@
<template> <template>
<div class="page projects--page"> <div class="page projects--page">
<Hero :title="staticData.hero"/> <Hero :title="staticData.hero"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<h2 class="title">{{staticData.t1}}</h2> <h2 class="title">{{ staticData.t1 }}</h2>
<p>{{staticData.t2}}</p> <p>{{ staticData.t2 }}</p>
<p>{{staticData.t3}}</p> <p>{{ staticData.t3 }}</p>
<div class="projects" v-if="projects.length"> <div class="projects" v-if="projects.length">
<div class="project anim-fadeIn" v-for="(item,index) in projects" :key="item._id"> <div class="project anim-fadeIn" v-for="(item,index) in projects" :key="item._id">
<div :id="`project_${index}`"> <div :id="`project_${index}`">
<div class="imgBox" v-for="image in item.images" :key="image._id"> <div class="imgBox" v-for="image in item.images" :key="image._id">
<img class="bg" :src="image.image" alt=""> <img class="bg" :src="image.image" alt="">
<img class="img" :src="image.image" alt=""> <img class="img" :src="image.image" alt="">
</div> </div>
</div> </div>
<div class="caption"> <div class="caption">
<h4>{{item.project_details[$route.params.lang].name}}</h4> <h4>{{ item.project_details[$route.params.lang].name }}</h4>
<p class="description">{{item.project_details[$route.params.lang].description}}</p> <p class="description">{{ item.project_details[$route.params.lang].description }}</p>
<p> <p>
<span>{{staticData.t6}}</span> <span>{{ staticData.t6 }}</span>
<span>{{jDate(item.date)}}</span> <span>{{ jDate(item.date) }}</span>
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<div class="no-project" v-else> <div class="no-project" v-else>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<p>{{staticData.t7}}</p> <p>{{ staticData.t7 }}</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s2"> <section class="s2">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2 class="title">{{staticData.t4}}</h2> <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> <nuxt-link :to="{name: 'lang-contact',params:{lang: $route.params.lang}}" class="btn btn-reverse-fill">{{ staticData.t5 }}</nuxt-link>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</div> </div>
</template> </template>
<script> <script>
if (process.client) require('slick-carousel') if (process.client) require('slick-carousel')
import moment from "moment-jalaali" import moment from "moment-jalaali"
import {fadeInAnimation} from "~/mixins/animations" import {fadeInAnimation} from "~/mixins/animations"
export default { export default {
data() { data() {
return { return {
projects: null projects: null
} }
}, },
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.projects[this.$route.params.lang] return this.$store.state.staticData.projects[this.$route.params.lang]
} }
}, },
methods: { methods: {
jDate(date) { jDate(date) {
if (this.$route.params.lang === 'fa') return moment(date).format('jYYYY/jMM/jDD') if (this.$route.params.lang === 'fa') return moment(date).jYear()
else return date.split(' ')[0] else return moment(date).year()
} }
}, },
mixins: [fadeInAnimation], mixins: [fadeInAnimation],
mounted() { mounted() {
this.projects.forEach((item, index) => { this.projects.forEach((item, index) => {
$(`#project_${index}`).slick({ $(`#project_${index}`).slick({
slidesToShow: 1, slidesToShow: 1,
centerMode: true, centerMode: true,
centerPadding: '150px', centerPadding: '150px',
infinite: true, infinite: true,
arrows: true, arrows: true,
responsive: [ responsive: [
{ {
breakpoint: 768, breakpoint: 768,
settings: { settings: {
slidesToShow: 2, slidesToShow: 2,
centerMode: false centerMode: false
} }
}, },
{ {
breakpoint: 575, breakpoint: 575,
settings: { settings: {
slidesToShow: 1, slidesToShow: 1,
centerMode: false centerMode: false
} }
} }
] ]
}) })
}) })
}, },
head() { head() {
return { return {
title: this.staticData.hero title: this.staticData.hero
} }
}, },
async asyncData({$axios}) { async asyncData({$axios}) {
const projects = await $axios.get(`/api/public/projects`) const projects = await $axios.get(`/api/public/projects`)
return { return {
projects: projects.data projects: projects.data
} }
} }
} }
</script> </script>
+43 -43
View File
@@ -1,49 +1,49 @@
<template> <template>
<div class="page tech-info--page"> <div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/> <Hero :title="staticData.title"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="content gDesign"> <div class="content gDesign">
<h2 class="first">{{staticData.t1}}</h2> <h2 class="first">{{ staticData.t1 }}</h2>
<p>{{staticData.t2}}</p> <p>{{ staticData.t2 }}</p>
<p v-html="staticData.t3"></p> <p v-html="staticData.t3"></p>
<p>{{staticData.t4}}</p> <p>{{ staticData.t4 }}</p>
<br> <br>
<br> <br>
<p>{{staticData.t5}}</p> <p>{{ staticData.t5 }}</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<section class="s2"> <section class="s2">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h2 class="title">{{staticData.t6}}</h2> <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> <nuxt-link :to="{name: 'lang-calculation',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t7 }}</nuxt-link>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<CustomersCommunication/> <CustomersCommunication/>
</div> </div>
</template> </template>
<script> <script>
import {fadeInAnimation} from "~/mixins/animations" import {fadeInAnimation} from "~/mixins/animations"
export default { export default {
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.gDesign[this.$route.params.lang] return this.$store.state.staticData.gDesign[this.$route.params.lang]
} }
}, },
mixins: [fadeInAnimation], mixins: [fadeInAnimation],
head() { head() {
return { return {
title: this.staticData.title title: this.staticData.title
} }
}, },
} }
</script> </script>
+56 -68
View File
@@ -1,79 +1,67 @@
<template> <template>
<div class="page tech-info--page"> <div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/> <Hero :title="staticData.title"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="content gStandard"> <div class="content gStandard">
<h2 class="first">{{staticData.t1}}</h2> <h2 class="first">{{ staticData.t1 }}</h2>
<p>{{staticData.t2}}</p> <p>{{ staticData.t2 }}</p>
<h2>{{staticData.t3}}</h2> <h2>{{ staticData.t3 }}</h2>
<p>{{staticData.t4}}</p> <p>{{ staticData.t4 }}</p>
<p>{{staticData.t5}}</p> <p>{{ staticData.t5 }}</p>
<h2>{{staticData.t6}}</h2> <h2>{{ staticData.t6 }}</h2>
<p>{{staticData.t7}}</p> <p>{{ staticData.t7 }}</p>
<img class="i1 anim-fadeIn" src="~/assets/img/tech-info/g-standard.png" alt=""> <img class="i1 anim-fadeIn" src="~/assets/img/tech-info/g-standard.png" alt="">
<h2>{{staticData.t8}}</h2> <h2>{{ staticData.t8 }}</h2>
<p>{{staticData.t9}}</p> <p>{{ staticData.t9 }}</p>
<img class="i2 anim-fadeIn" src="~/assets/img/tech-info/DIN24537.png" alt=""> <img class="i2 anim-fadeIn" src="~/assets/img/tech-info/DIN24537.png" alt="">
<h2>{{staticData.t10}}</h2> <h2>{{ staticData.t10 }}</h2>
<p>{{staticData.t11}}</p> <p>{{ staticData.t11 }}</p>
<p>{{staticData.t12}}</p> <p>{{ staticData.t12 }}</p>
<p>{{staticData.t13}}</p> <p>{{ staticData.t13 }}</p>
<ul> <ul>
<li> <li v-for="item in $store.state.staticData.about.en.s4" :key="item.title">
<p>{{staticData.t14}}</p> <a :href="`/standards_pdf/${item.link.url}`" download target="_blank">{{ item.title }}</a>
</li> </li>
<li> </ul>
<p>{{staticData.t15}}</p> </div>
</li> </div>
<li> </div>
<p>{{staticData.t16}}</p> </section>
</li> <section class="s2">
<li> <div class="container">
<p>{{staticData.t17}}</p> <div class="row">
</li> <div class="col-12">
<li> <h2 class="title">{{ staticData.t19 }}</h2>
<p>{{staticData.t18}}</p> <nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{ staticData.t20 }}</nuxt-link>
</li> </div>
</ul> </div>
</div> </div>
</div> </section>
</div> <CustomersCommunication/>
</section> </div>
<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> </template>
<script> <script>
import {fadeInAnimation} from "~/mixins/animations" import {fadeInAnimation} from "~/mixins/animations"
export default { export default {
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.gStandard[this.$route.params.lang] return this.$store.state.staticData.gStandard[this.$route.params.lang]
} }
}, },
mixins: [fadeInAnimation], mixins: [fadeInAnimation],
head() { head() {
return { return {
title: this.staticData.title title: this.staticData.title
} }
} }
} }
</script> </script>
+1 -1
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="page tech-info--page"> <div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/> <Hero :title="staticData.title"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
+80 -70
View File
@@ -1,77 +1,87 @@
<template> <template>
<div class="page tech-info--page"> <div class="page tech-info--page latin-digits">
<Hero :title="staticData.title"/> <Hero :title="staticData.title"/>
<section class="s1"> <section class="s1">
<div class="container"> <div class="container">
<div class="panel"> <div class="panel">
<div class="content gUsage"> <div class="content gUsage">
<h2 class="first">{{staticData.t1}}</h2> <h2 class="first">{{ staticData.t1 }}</h2>
<p v-html="staticData.t2"></p> <p v-html="staticData.t2"></p>
<p>{{staticData.t3}}</p> <p>{{ staticData.t3 }}</p>
<p>{{staticData.t4}}</p> <p>{{ staticData.t4 }}</p>
<p>{{staticData.t5}}</p> <p>{{ staticData.t5 }}</p>
<ul> <ul>
<li> <li>
<p>{{staticData.t6}}</p> <p>{{ staticData.t6 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t7}}</p> <p>{{ staticData.t7 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t8}}</p> <p>{{ staticData.t8 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t9}}</p> <p>{{ staticData.t9 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t10}}</p> <p>{{ staticData.t10 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t11}}</p> <p>{{ staticData.t11 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t12}}</p> <p>{{ staticData.t12 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t13}}</p> <p>{{ staticData.t13 }}</p>
</li> </li>
<li> <li>
<p>{{staticData.t14}}</p> <p>{{ staticData.t14 }}</p>
</li> </li>
</ul> </ul>
</div>
</div> <h2 class="first mt-5">{{ staticData.t17 }}</h2>
</div> <div class="images">
</section> <img src="~/assets/img/grating-usage/4.jpg" :alt="staticData.title">
<section class="s2"> <img src="~/assets/img/grating-usage/8.jpg" :alt="staticData.title">
<div class="container"> <img src="~/assets/img/grating-usage/13.jpg" :alt="staticData.title">
<div class="row"> <img src="~/assets/img/grating-usage/88-wood-1.jpg" :alt="staticData.title">
<div class="col-12"> <img src="~/assets/img/grating-usage/industri-2.jpg" :alt="staticData.title">
<h2 class="title">{{staticData.t15}}</h2> <img src="~/assets/img/grating-usage/infills-1b.jpg" :alt="staticData.title">
<nuxt-link :to="{name: 'lang-products',params: {lang: $route.params.lang}}" class="btn btn-primary">{{staticData.t16}}</nuxt-link> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<CustomersCommunication/> <section class="s2">
</div> <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> </template>
<script> <script>
import {fadeInAnimation} from "~/mixins/animations" import {fadeInAnimation} from "~/mixins/animations"
export default { export default {
computed: { computed: {
staticData() { staticData() {
return this.$store.state.staticData.gUsage[this.$route.params.lang] return this.$store.state.staticData.gUsage[this.$route.params.lang]
} }
}, },
mixins: [fadeInAnimation], mixins: [fadeInAnimation],
head() { head() {
return { return {
title: this.staticData.title title: this.staticData.title
} }
} }
} }
</script> </script>
+173 -172
View File
@@ -1,191 +1,192 @@
<template> <template>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<admin-title-bar :title="title"> <admin-title-bar :title="title">
<el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button> <el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button>
<el-button type="success" @click="upload">بروزرسانی</el-button> <el-button type="success" @click="upload">بروزرسانی</el-button>
</admin-title-bar> </admin-title-bar>
<div class="col-12"> <div class="col-12">
<admin-panel> <admin-panel>
<h2>تصویر</h2> <h2>تصویر</h2>
<el-divider></el-divider> <el-divider></el-divider>
<img :src="post.cover" alt="" style="width: 100%"> <img :src="post.cover" alt="" style="width: 100%">
<input type="file" ref="cover" @change="preview"> <input type="file" ref="cover" @change="preview">
<p class="err" v-if="validation.cover">{{validation.cover.msg}}</p> <p class="err" v-if="validation.cover">{{ validation.cover.msg }}</p>
<el-form class="secondTitle"> <el-form class="secondTitle">
<el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی"> <el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی">
<el-select v-model="post.category" placeholder="انتخاب کنید"> <el-select v-model="post.category" placeholder="انتخاب کنید">
<el-option <el-option
v-for="item in blogCategories" v-for="item in blogCategories"
:key="item._id" :key="item._id"
:label="item.blogCategory_details.fa.name" :label="item.blogCategory_details.fa.name"
:value="item._id"> :value="item._id">
</el-option> </el-option>
</el-select> </el-select>
<p class="err" v-if="validation.category">{{validation.category.msg}}</p> <p class="err" v-if="validation.category">{{ validation.category.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="published" label="وضعیت انتشار پست"> <el-form-item prop="published" label="وضعیت انتشار پست">
<el-switch v-model="post.published" style="margin-right: 15px;"></el-switch> <el-switch v-model="post.published" style="margin-right: 15px;"></el-switch>
</el-form-item> </el-form-item>
</el-form> </el-form>
</admin-panel> </admin-panel>
</div> </div>
<!-- fa --> <!-- fa -->
<div class="col-6"> <div class="col-6">
<admin-panel> <admin-panel>
<h2>فارسی</h2> <h2>فارسی</h2>
<el-divider></el-divider> <el-divider></el-divider>
<el-form> <el-form>
<el-form-item prop="title" :class="validation.fa_title ? 'is-error' : ''" label="عنوان"> <el-form-item prop="title" :class="validation.fa_title ? 'is-error' : ''" label="عنوان">
<el-input v-model="post.post_details.fa.title"></el-input> <el-input v-model="post.post_details.fa.title"></el-input>
<p class="err" v-if="validation.fa_title">{{validation.fa_title.msg}}</p> <p class="err" v-if="validation.fa_title">{{ validation.fa_title.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="short_description" :class="validation.fa_short_description ? 'is-error' : ''" label="توضیح کوتاه"> <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> <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> <p class="err" v-if="validation.fa_short_description">{{ validation.fa_short_description.msg }}</p>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-divider></el-divider> <el-divider></el-divider>
<h6 style="margin-bottom: 30px;">توضیحات پست</h6> <h6 style="margin-bottom: 30px;">توضیحات پست</h6>
<client-only> <client-only>
<ckeditor v-model="post.post_details.fa.description" :config="editorConfig"></ckeditor> <ckeditor v-model="post.post_details.fa.description" :config="editorConfig"></ckeditor>
<p class="err" v-if="validation.fa_description">{{validation.fa_description.msg}}</p> <p class="err" v-if="validation.fa_description">{{ validation.fa_description.msg }}</p>
</client-only> </client-only>
</admin-panel> </admin-panel>
</div> </div>
<!-- en --> <!-- en -->
<div class="col-6"> <div class="col-6">
<admin-panel> <admin-panel>
<h2>انگلیسی</h2> <h2>انگلیسی</h2>
<el-divider></el-divider> <el-divider></el-divider>
<el-form> <el-form>
<el-form-item prop="title" :class="validation.en_title ? 'is-error' : ''" label="عنوان"> <el-form-item prop="title" :class="validation.en_title ? 'is-error' : ''" label="عنوان">
<el-input v-model="post.post_details.en.title"></el-input> <el-input v-model="post.post_details.en.title"></el-input>
<p class="err" v-if="validation.en_title">{{validation.en_title.msg}}</p> <p class="err" v-if="validation.en_title">{{ validation.en_title.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="short_description" :class="validation.en_short_description ? 'is-error' : ''" label="توضیح کوتاه"> <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> <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> <p class="err" v-if="validation.en_short_description">{{ validation.en_short_description.msg }}</p>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-divider></el-divider> <el-divider></el-divider>
<h6 style="margin-bottom: 30px;">توضیحات پست</h6> <h6 style="margin-bottom: 30px;">توضیحات پست</h6>
<client-only> <client-only>
<ckeditor v-model="post.post_details.en.description" :config="editorConfig_en"></ckeditor> <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> <p class="err" v-if="validation.en_description">{{ validation.en_description.msg }}</p>
</client-only> </client-only>
</admin-panel> </admin-panel>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
post: null, post: null,
blogCategories: null, blogCategories: null,
editorConfig: { editorConfig: {
language: 'fa', language: 'fa',
extraPlugins: ['bidi', 'justify'] extraPlugins: ['bidi', 'justify']
},
editorConfig_en: {
language: 'en',
extraPlugins: ['bidi', 'justify']
},
validation: {},
uploading: false,
uploadProgress: null
}
}, },
computed: { editorConfig_en: {
title() { language: 'en',
if (!this.uploading) { extraPlugins: ['bidi', 'justify']
return 'ویرایش پست'
} else {
return this.uploadProgress
}
}
}, },
methods: { validation: {},
upload() { uploading: false,
this.validation = {} uploadProgress: null
const data = new FormData() }
},
data.append('fa_title', this.post.post_details.fa.title) computed: {
data.append('en_title', this.post.post_details.en.title) title() {
if (!this.uploading) {
data.append('fa_description', this.post.post_details.fa.description) return 'ویرایش پست'
data.append('en_description', this.post.post_details.en.description) } else {
return this.uploadProgress
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
}
} }
} }
},
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> </script>
+107 -82
View File
@@ -1,90 +1,115 @@
<template> <template>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<admin-title-bar :title="title"></admin-title-bar> <admin-title-bar :title="title"></admin-title-bar>
<div class="col-6"> <div class="col-12">
<admin-panel> <admin-panel>
<h2>افزودن یا بروزرسانی کاتالوگ:</h2> <h2>افزودن یا بروزرسانی کاتالوگ:</h2>
<el-divider></el-divider> </admin-panel>
<el-form> </div>
<input type="file" ref="file"> <div class="col-6">
<el-button @click="upload" type="success">افزودن</el-button> <admin-panel>
<p style="color: red;" v-if="validation.pdf">{{validation.pdf.msg}}</p> <h2>کاتالوگ فارسی:</h2>
</el-form> <el-divider></el-divider>
<el-divider></el-divider> <el-form>
<a v-if="catalog && catalog.file" :href="catalog.file" target="_blank"> <input type="file" ref="file_fa">
<el-button>دانلود و مشاهده کاتالوگ فعلی</el-button> <el-button @click="upload('fa')" type="success">افزودن</el-button>
</a> <p style="color: red;" v-if="validation.pdf && locale === 'fa'">{{ validation.pdf.msg }}</p>
</admin-panel> </el-form>
</div> <el-divider></el-divider>
</div> <a v-if="catalog && catalog.file && catalog.file.fa" :href="catalog.file.fa" target="_blank">
</div> <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> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
catalog: null, catalog: null,
validation: {}, locale: null,
uploading: false, validation: {},
uploadProgress: null uploading: false,
} uploadProgress: null
}, }
head() { },
return { head() {
title: this.title, return {
} title: this.title,
}, }
computed: { },
title() { computed: {
if (!this.uploading) { title() {
return 'آپلود کاتالوگ اصلی سایت' if (!this.uploading) {
} else { return 'آپلود کاتالوگ اصلی سایت'
return this.uploadProgress } 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
}
} }
} }
},
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> </script>
+58 -49
View File
@@ -1,57 +1,66 @@
<template> <template>
<div class="col-12"> <div class="col-12">
<el-form @submit.native.prevent="loginFunction"> <el-form @submit.native.prevent="loginFunction">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12 d-flex justify-content-center align-items-center" style="min-height: calc(100vh - 60px);">
<admin-panel style="width: 50%;margin: 300px auto 0"> <admin-panel class="login">
<h1 style="text-align: center;">ورود به پنل مدیریت</h1> <h1 style="text-align: center;">ورود به پنل مدیریت</h1>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="username" :class="validation.username ? 'is-error' : ''" label="نام کاربری"> <el-form-item prop="username" :class="validation.username ? 'is-error' : ''" label="نام کاربری">
<el-input v-model="login.username"></el-input> <el-input v-model="login.username"></el-input>
<p class="err" v-if="validation.username">{{validation.username.msg}}</p> <p class="err" v-if="validation.username">{{ validation.username.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="password" :class="validation.password ? 'is-error' : ''" label="پسورد"> <el-form-item prop="password" :class="validation.password ? 'is-error' : ''" label="پسورد">
<el-input v-model="login.password" type="password"></el-input> <el-input v-model="login.password" type="password"></el-input>
<p class="err" v-if="validation.password">{{validation.password.msg}}</p> <p class="err" v-if="validation.password">{{ validation.password.msg }}</p>
</el-form-item> </el-form-item>
<el-checkbox v-model="login.remember_me" style="display: block;margin-top: 30px;margin-bottom: 15px;">مرا به خاطر بسپار</el-checkbox> <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> <el-button size="small" native-type="submit">ورود</el-button>
</admin-panel> </admin-panel>
<h1 v-if="$auth.loggedIn">{{$auth.user.name}}</h1> <h1 v-if="$auth.loggedIn">{{ $auth.user.name }}</h1>
</div> </div>
</div> </div>
</div> </div>
</el-form> </el-form>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
login: { login: {
username: '', username: '',
password: '', password: '',
remember_me: false remember_me: false
},
validation: {}
}
}, },
methods: { validation: {}
loginFunction() { }
this.validation = {} },
this.$auth.loginWith('local', {data: this.login}) methods: {
.then(res => { loginFunction() {
this.$router.push('/admin') this.validation = {}
}) this.$auth.loginWith('local', {data: this.login})
.catch(err => { .then(res => {
this.validation = err.response.data.validation this.$router.push('/admin')
}) })
} .catch(err => {
}, this.validation = err.response.data.validation
layout: 'admin' })
} }
},
layout: 'admin'
}
</script> </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
+139 -117
View File
@@ -1,129 +1,151 @@
<template> <template>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<admin-title-bar :title="title"> <admin-title-bar :title="title">
<nuxt-link :to="{name: 'admin-products-new'}"> <nuxt-link :to="{name: 'admin-products-new'}">
<el-button type="success">جدید</el-button> <el-button type="success">جدید</el-button>
</nuxt-link> </nuxt-link>
</admin-title-bar> </admin-title-bar>
<div class="col-lg-12"> <div class="col-lg-12">
<admin-panel> <admin-panel>
<el-table <el-button-group class="filterBtns">
:data="products" <el-button :type="filter ? 'success' : 'primary'" @click="filter = true">محصولات صفحه اصلی</el-button>
style="width: 100%"> <el-button :type="!filter ? 'success' : 'primary'" @click="filter = false">تمام محصولات</el-button>
<el-table-column </el-button-group>
type="index" <el-divider></el-divider>
label="#"> <el-table
</el-table-column> :data="filteredProducts"
style="width: 100%">
<el-table-column
type="index"
label="#">
</el-table-column>
<el-table-column <el-table-column
label="تصویر" label="تصویر"
width="230"> width="230">
<template slot-scope="scope"> <template slot-scope="scope">
<el-image <el-image
style="width: 100%; height: 100%" style="width: 100%; height: 100%"
:src="scope.row.cover" :src="scope.row.thumb"
fit="fit"> fit="fit">
</el-image> </el-image>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="product_details.fa.name" prop="product_details.fa.name"
label="نام" label="نام"
width=""> width="">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="category" prop="category"
label="دسته بندی" label="دسته بندی"
width=""> width="">
<template slot-scope="scope"> <template slot-scope="scope">
{{categoryName(scope.row.category)}} {{ categoryName(scope.row.category) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="ویرایش" label="ویرایش"
width="150" width="150"
align="left"> align="left">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="warning" plain icon="el-icon-edit" @click="edit(scope.row._id)"></el-button> <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> <el-button type="danger" plain icon="el-icon-delete" @click="del(scope.row._id)"></el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</admin-panel> </admin-panel>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
title: 'لیست محصولات', title: 'لیست محصولات',
products: null, products: null,
productCategories: null productCategories: null,
} filter: false
}, }
head() { },
return { head() {
title: this.title, return {
} title: this.title,
}, }
methods: { },
categoryName(id) { computed: {
let category = this.productCategories.filter(item => { filteredProducts() {
return item._id === id if (this.filter) return this.products.filter(item => item.favorite)
}) else return this.products
return category[0].category_details.fa.name
},
edit(id) {
this.$router.push(`/admin/products/${id}`)
}, }
del(id) { },
this.$confirm('این محصول حذف شود؟', 'هشدار', { methods: {
confirmButtonText: 'بله', categoryName(id) {
cancelButtonText: 'لغو', let category = this.productCategories.filter(item => {
type: 'warning' return item._id === id
}).then(() => { })
this.$axios.delete(`/api/private/products/${id}`) return category[0].category_details.fa.name
.then(response => { },
this.products = this.products.filter(item => { edit(id) {
return item._id !== id this.$router.push(`/admin/products/${id}`)
})
this.$message({ },
type: 'success', del(id) {
message: 'آیتم حذف شد' this.$confirm('این محصول حذف شود؟', 'هشدار', {
}) confirmButtonText: 'بله',
}) cancelButtonText: 'لغو',
.catch(err => { type: 'warning'
this.$message({ }).then(() => {
type: 'error', this.$axios.delete(`/api/private/products/${id}`)
message: err.response.data.message .then(response => {
}) this.products = this.products.filter(item => {
}) return item._id !== id
}).catch(() => { })
this.$message({ this.$message({
type: 'warning', type: 'success',
message: 'عملیات لغو شد' message: 'آیتم حذف شد'
}); })
}); })
} .catch(err => {
}, this.$message({
layout: 'admin', type: 'error',
async asyncData({$axios, store}) { message: err.response.data.message
let products = await $axios.get(`/api/public/products`) })
let productCategories = await $axios.get(`/api/public/productCategories`) })
return { }).catch(() => {
products: products.data, this.$message({
productCategories: productCategories.data 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> </script>
<style lang="scss">
.filterBtns {
span {
color: #fff !important;
}
}
</style>
+384 -378
View File
@@ -1,439 +1,445 @@
<template> <template>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<admin-title-bar :title="title"> <admin-title-bar :title="title">
<el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button> <el-button @click="$router.back()" type="primary">برگشت به صفحه قبل</el-button>
<el-button type="success" @click="upload">ایجاد</el-button> <el-button type="success" @click="upload">ایجاد</el-button>
</admin-title-bar> </admin-title-bar>
<div class="col-6"> <div class="col-6">
<admin-panel> <admin-panel>
<p style="margin-bottom: 50px;color: green;font-weight: bold;font-size: 20px;">ابتدا محصول را ثبت کرده، سپس در مرحله بعد عکس های بیشتر و ویژگی های محصول را وارد کنید.</p> <p style="margin-bottom: 50px;color: green;font-weight: bold;font-size: 20px;">ابتدا محصول را ثبت کرده، سپس در مرحله بعد عکس های بیشتر و ویژگی های محصول را وارد کنید.</p>
<el-form> <el-form>
<el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی"> <el-form-item prop="category" :class="validation.category ? 'is-error' : ''" label="دسته بندی">
<el-select v-model="formData.category" placeholder="انتخاب کنید"> <el-select v-model="formData.category" placeholder="انتخاب کنید">
<el-option <el-option
v-for="item in productCategories" v-for="item in productCategories"
:key="item._id" :key="item._id"
:label="item.category_details.fa.name" :label="item.category_details.fa.name"
:value="item._id"> :value="item._id">
</el-option> </el-option>
</el-select> </el-select>
<p class="err" v-if="validation.category">{{validation.category.msg}}</p> <p class="err" v-if="validation.category">{{ validation.category.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="published" label="بخش دوم نمایش داده شود"> <el-form-item prop="published" label="بخش دوم نمایش داده شود">
<el-switch v-model="formData.more_section" style="margin-right: 15px;"></el-switch> <el-switch v-model="formData.more_section" style="margin-right: 15px;"></el-switch>
</el-form-item> </el-form-item>
<el-form-item prop="published" label="دارای فایل های قابل دانلود باشد"> <el-form-item prop="published" label="دارای فایل های قابل دانلود باشد">
<el-switch v-model="formData.download_section" style="margin-right: 15px;"></el-switch> <el-switch v-model="formData.download_section" style="margin-right: 15px;"></el-switch>
</el-form-item> </el-form-item>
</el-form> <el-form-item prop="published" label="در صفحه اصلی باشد">
</admin-panel> <el-switch v-model="formData.favorite" style="margin-right: 15px;"></el-switch>
</div> </el-form-item>
<div class="col-6"> </el-form>
<admin-panel> </admin-panel>
<h2>کاور</h2> </div>
<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"> <div class="col-6">
<admin-panel> <admin-panel>
<el-form> <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>
<h2 style="color: #000;font-weight: bold;font-size: 30px;">فارسی</h2> <div class="col-6">
<el-divider></el-divider> <admin-panel>
<el-form>
<el-form-item prop="title" :class="validation.fa_name ? 'is-error' : ''" label="نام"> <h2 style="color: #000;font-weight: bold;font-size: 30px;">فارسی</h2>
<el-input v-model="formData.product_details.fa.name"></el-input> <el-divider></el-divider>
<p class="err" v-if="validation.fa_name">{{validation.fa_name.msg}}</p>
</el-form-item> <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-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> <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> <p class="err" v-if="validation.fa_short_description">{{ validation.fa_short_description.msg }}</p>
</el-form-item> </el-form-item>
<h3>بخش اول صفحه</h3> <h3>بخش اول صفحه</h3>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_page_title ? 'is-error' : ''" label="عنوان"> <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> <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> <p class="err" v-if="validation.fa_page_title">{{ validation.fa_page_title.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.fa_page_description ? 'is-error' : ''" label="توضیحات"> <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> <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> <p class="err" v-if="validation.fa_page_description">{{ validation.fa_page_description.msg }}</p>
</el-form-item> </el-form-item>
<h3>بخش دوم صفحه</h3> <h3>بخش دوم صفحه</h3>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_more_title1 ? 'is-error' : ''" label="عنوان اول"> <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> <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> <p class="err" v-if="validation.fa_more_title1">{{ validation.fa_more_title1.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.fa_more_description1 ? 'is-error' : ''" label="توضیح اول"> <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> <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> <p class="err" v-if="validation.fa_more_description1">{{ validation.fa_more_description1.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.fa_more_title2 ? 'is-error' : ''" label="عنوان دوم"> <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> <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> <p class="err" v-if="validation.fa_more_title2">{{ validation.fa_more_title2.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.fa_more_description2 ? 'is-error' : ''" label="توضیح دوم"> <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> <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> <p class="err" v-if="validation.fa_more_description2">{{ validation.fa_more_description2.msg }}</p>
</el-form-item> </el-form-item>
<h3>بخش سوم صفحه (جدول و توضیحات)</h3> <h3>بخش سوم صفحه (جدول و توضیحات)</h3>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="title" :class="validation.fa_chart_title ? 'is-error' : ''" label="عنوان جدول"> <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> <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> <p class="err" v-if="validation.fa_chart_title">{{ validation.fa_chart_title.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.fa_chart_description ? 'is-error' : ''" label="توضیحات جدول"> <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> <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> <p class="err" v-if="validation.fa_chart_description">{{ validation.fa_chart_description.msg }}</p>
</el-form-item> </el-form-item>
</el-form> </el-form>
</admin-panel> </admin-panel>
</div> </div>
<div class="col-6"> <div class="col-6">
<admin-panel> <admin-panel>
<el-form> <el-form>
<h2 style="color: #000;font-weight: bold;font-size: 30px;">انگلیسی</h2> <h2 style="color: #000;font-weight: bold;font-size: 30px;">انگلیسی</h2>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_name ? 'is-error' : ''" label="نام"> <el-form-item prop="title" :class="validation.en_name ? 'is-error' : ''" label="نام">
<el-input v-model="formData.product_details.en.name"></el-input> <el-input v-model="formData.product_details.en.name"></el-input>
<p class="err" v-if="validation.en_name">{{validation.en_name.msg}}</p> <p class="err" v-if="validation.en_name">{{ validation.en_name.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_short_description ? 'is-error' : ''" label="توضیح کوتاه"> <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> <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> <p class="err" v-if="validation.en_short_description">{{ validation.en_short_description.msg }}</p>
</el-form-item> </el-form-item>
<h3>بخش اول صفحه</h3> <h3>بخش اول صفحه</h3>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_page_title ? 'is-error' : ''" label="عنوان"> <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> <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> <p class="err" v-if="validation.en_page_title">{{ validation.en_page_title.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_page_description ? 'is-error' : ''" label="توضیحات"> <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> <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> <p class="err" v-if="validation.en_page_description">{{ validation.en_page_description.msg }}</p>
</el-form-item> </el-form-item>
<h3>بخش دوم صفحه</h3> <h3>بخش دوم صفحه</h3>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_more_title1 ? 'is-error' : ''" label="عنوان اول"> <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> <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> <p class="err" v-if="validation.en_more_title1">{{ validation.en_more_title1.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_more_description1 ? 'is-error' : ''" label="توضیح اول"> <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> <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> <p class="err" v-if="validation.en_more_description1">{{ validation.en_more_description1.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_more_title2 ? 'is-error' : ''" label="عنوان دوم"> <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> <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> <p class="err" v-if="validation.en_more_title2">{{ validation.en_more_title2.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_more_description2 ? 'is-error' : ''" label="توضیح دوم"> <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> <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> <p class="err" v-if="validation.en_more_description2">{{ validation.en_more_description2.msg }}</p>
</el-form-item> </el-form-item>
<h3>بخش سوم صفحه (جدول و توضیحات)</h3> <h3>بخش سوم صفحه (جدول و توضیحات)</h3>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item prop="title" :class="validation.en_chart_title ? 'is-error' : ''" label="عنوان جدول"> <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> <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> <p class="err" v-if="validation.en_chart_title">{{ validation.en_chart_title.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_chart_description ? 'is-error' : ''" label="توضیحات جدول"> <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> <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> <p class="err" v-if="validation.en_chart_description">{{ validation.en_chart_description.msg }}</p>
</el-form-item> </el-form-item>
</el-form> </el-form>
</admin-panel> </admin-panel>
</div> </div>
<div class="col-6"> <div class="col-6">
<admin-panel> <admin-panel>
<h2>عکس اول بخش دوم</h2> <h2>عکس اول بخش دوم</h2>
<el-divider></el-divider> <el-divider></el-divider>
<img :src="formData.more_section_image1" alt="" style="width: 100%;max-width: 300px;display: block"> <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"> <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 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> <p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 778px عرض و 395px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<h2 class="secondTitle">عکس دوم بخش دوم</h2> <h2 class="secondTitle">عکس دوم بخش دوم</h2>
<el-divider></el-divider> <el-divider></el-divider>
<img :src="formData.more_section_image2" alt="" style="width: 100%;max-width: 300px;display: block"> <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"> <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 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> <p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 778px عرض و 395px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<!-- --> <!-- -->
<h2 class="secondTitle">عکس اول شماتیک بخش سوم</h2> <h2 class="secondTitle">عکس اول شماتیک بخش سوم</h2>
<el-divider></el-divider> <el-divider></el-divider>
<img :src="formData.render_image1" alt="" style="width: 100%;max-width: 300px;display: block"> <img :src="formData.render_image1" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="render_image1" @change="previewRender_image1"> <input type="file" ref="render_image1" @change="previewRender_image1">
<p class="err" v-if="validation.render_image1">{{validation.render_image1.msg}}</p> <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> <p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 300px عرض و 300px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<el-form> <el-form>
<el-form-item prop="title" :class="validation.fa_render_caption1 ? 'is-error' : ''" label="کپشن فارسی"> <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> <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> <p class="err" v-if="validation.fa_render_caption1">{{ validation.fa_render_caption1.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_render_caption1 ? 'is-error' : ''" label="کپشن انگلیسی"> <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> <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> <p class="err" v-if="validation.en_render_caption1">{{ validation.en_render_caption1.msg }}</p>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- --> <!-- -->
<h2 class="secondTitle">عکس دوم شماتیک بخش سوم</h2> <h2 class="secondTitle">عکس دوم شماتیک بخش سوم</h2>
<el-divider></el-divider> <el-divider></el-divider>
<img :src="formData.render_image2" alt="" style="width: 100%;max-width: 300px;display: block"> <img :src="formData.render_image2" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="render_image2" @change="previewRender_image2"> <input type="file" ref="render_image2" @change="previewRender_image2">
<p class="err" v-if="validation.render_image2">{{validation.render_image2.msg}}</p> <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> <p v-else style="margin-top: 20px;color: green;">ابعاد تصویر باید 300px عرض و 300px ارتفاع باشد، در غیر این صورت عکس به صورت اوتوماتیک برش خواهد خورد.</p>
<el-form> <el-form>
<el-form-item prop="title" :class="validation.fa_render_caption2 ? 'is-error' : ''" label="کپشن فارسی"> <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> <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> <p class="err" v-if="validation.fa_render_caption2">{{ validation.fa_render_caption2.msg }}</p>
</el-form-item> </el-form-item>
<el-form-item prop="title" :class="validation.en_render_caption2 ? 'is-error' : ''" label="کپشن انگلیسی"> <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> <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> <p class="err" v-if="validation.en_render_caption2">{{ validation.en_render_caption2.msg }}</p>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- --> <!-- -->
<h2 class="secondTitle">عکس جدول مشخصات محصول</h2> <h2 class="secondTitle">عکس جدول مشخصات محصول</h2>
<el-divider></el-divider> <el-divider></el-divider>
<img :src="formData.chart_image" alt="" style="width: 100%;max-width: 300px;display: block"> <img :src="formData.chart_image" alt="" style="width: 100%;max-width: 300px;display: block">
<input type="file" ref="chart_image" @change="previewChart_image"> <input type="file" ref="chart_image" @change="previewChart_image">
<p class="err" v-if="validation.chart_image">{{validation.chart_image.msg}}</p> <p class="err" v-if="validation.chart_image">{{ validation.chart_image.msg }}</p>
</admin-panel> </admin-panel>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
formData: { formData: {
cover: '', cover: '',
more_section_image1: '', more_section_image1: '',
more_section_image2: '', more_section_image2: '',
render_image1: '', render_image1: '',
render_image2: '', render_image2: '',
chart_image: '', chart_image: '',
category: '', category: '',
more_section: true, more_section: true,
download_section: true, download_section: true,
product_details: { favorite: false,
fa: { product_details: {
name: '', fa: {
short_description: '', name: '',
page_title: '', short_description: '',
page_description: '', page_title: '',
more_title1: '', page_description: '',
more_description1: '', more_title1: '',
more_title2: '', more_description1: '',
more_description2: '', more_title2: '',
render_caption1: '', more_description2: '',
render_caption2: '', render_caption1: '',
chart_title: '', render_caption2: '',
chart_description: '' chart_title: '',
}, chart_description: ''
en: { },
name: '', en: {
short_description: '', name: '',
page_title: '', short_description: '',
page_description: '', page_title: '',
more_title1: '', page_description: '',
more_description1: '', more_title1: '',
more_title2: '', more_description1: '',
more_description2: '', more_title2: '',
render_caption1: '', more_description2: '',
render_caption2: '', render_caption1: '',
chart_title: '', render_caption2: '',
chart_description: '' chart_title: '',
} chart_description: ''
} }
}, }
productCategories: null,
validation: {},
uploading: false,
uploadProgress: null
}
}, },
computed: { productCategories: null,
title() { validation: {},
if (!this.uploading) { uploading: false,
return 'افزودن محصول' uploadProgress: null
} else { }
return this.uploadProgress },
} computed: {
} title() {
}, if (!this.uploading) {
watch: { return 'افزودن محصول'
async locale(newVal, oldVal) { } else {
let productCategories = await this.$axios.get(`/api/public/productCategories/${newVal}`) return this.uploadProgress
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
}
} }
} }
},
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> </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 = {} export const mutations = {}
+870 -670
View File
File diff suppressed because it is too large Load Diff