LFFE-25 Implementation of print layout and Printable Page
This commit is contained in:
@@ -167,3 +167,10 @@ This set of fonts are used in this project under the license: (.....)
|
||||
url('./fonts/woff/Parastoo-Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
|
||||
url('./fonts/ttf/Parastoo-Bold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Bnazanin;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: url('./fonts/ttf/BNazanin.ttf') format('truetype');
|
||||
}
|
||||
|
||||
BIN
public/fonts/ttf/BNazanin.ttf
Normal file
BIN
public/fonts/ttf/BNazanin.ttf
Normal file
Binary file not shown.
BIN
public/images/logo.png
Normal file
BIN
public/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -17,6 +17,9 @@
|
||||
"online_message": "شما به اینترنت وصل هستید",
|
||||
"offline_message": "اتصال شما به اینترنت قطع شده است",
|
||||
"routing_to": "در حال انتقال به صفحه",
|
||||
"data_not_found": "اطلاعاتی یافت نشد!",
|
||||
"btn_print": "چاپ",
|
||||
"button_back_to_previous": "بازگشت به صفحه قبل",
|
||||
"header": {
|
||||
"open_profile": "پروفایل",
|
||||
"edit_profile": " پروفایل",
|
||||
@@ -205,7 +208,9 @@
|
||||
"upload_file": "صورت جلسه کارگروه استانی را بارگذاری کنید",
|
||||
"upload_file_required": "وارد کردن صورت جلسه کارگروه استانی الزامیست",
|
||||
"upload_file_unit": "فایل بارگذاری شده باید حداکثر 2Mb باشد",
|
||||
"upload_file_format": "فرمت قابل قبول : png,jpg,pdf"
|
||||
"upload_file_format": "فرمت قابل قبول : png,jpg,pdf",
|
||||
"print_appraisal_confirmation": "چاپ تاییدیه ارزیابی",
|
||||
"print_final_credit_amount": "چاپ صورت جلسه تعیین مبلغ نهایی"
|
||||
},
|
||||
"RefahiProvinceManager": {
|
||||
"name": "نام",
|
||||
|
||||
9
public/print.scss
Normal file
9
public/print.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
@media print {
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@page {
|
||||
size: A4;
|
||||
}
|
||||
}
|
||||
18
src/components/layouts/Print/Header/ProfileData.jsx
Normal file
18
src/components/layouts/Print/Header/ProfileData.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import {Avatar, Stack, Typography} from "@mui/material";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
|
||||
export default function ProfileData() {
|
||||
const {user} = useUser();
|
||||
return (
|
||||
<Stack alignItems="center" spacing={2} sx={{p: 3}}>
|
||||
<Avatar
|
||||
sx={{width: "80px", height: "80px"}}
|
||||
alt="User Image"
|
||||
src={user.avatar}
|
||||
/>
|
||||
<Typography sx={{fontSize: 15, fontWeight: 600}} textAlign="center">
|
||||
{user.username}
|
||||
</Typography>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
62
src/components/layouts/Print/Header/ProfileMenu.jsx
Normal file
62
src/components/layouts/Print/Header/ProfileMenu.jsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import {Avatar, IconButton, Menu, Tooltip} from "@mui/material";
|
||||
import {useState} from "react";
|
||||
import ProfileData from "./ProfileData";
|
||||
import ProfileOptions from "./ProfileOptions";
|
||||
import {useTranslations} from "next-intl";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
|
||||
function ProfileMenu() {
|
||||
const t = useTranslations();
|
||||
const [anchorElUser, setAnchorElUser] = useState(null);
|
||||
const {user} = useUser();
|
||||
|
||||
const handleOpenUserMenu = (event) => {
|
||||
setAnchorElUser(event.currentTarget);
|
||||
};
|
||||
const handleCloseUserMenu = () => {
|
||||
setAnchorElUser(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={t("header.open_profile")} arrow>
|
||||
<IconButton onClick={handleOpenUserMenu} sx={{p: 0}}>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
backgroundColor: "#fff",
|
||||
color: "primary.main",
|
||||
}}
|
||||
alt="User Image"
|
||||
src={user.avatar}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Menu
|
||||
MenuListProps={{sx: {py: 0}}}
|
||||
sx={{
|
||||
mt: 6,
|
||||
}}
|
||||
id="menu-appbar"
|
||||
anchorEl={anchorElUser}
|
||||
anchorOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
keepMounted
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
open={Boolean(anchorElUser)}
|
||||
onClose={handleCloseUserMenu}
|
||||
>
|
||||
<ProfileData/>
|
||||
<ProfileOptions handleCloseUserMenu={handleCloseUserMenu}/>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProfileMenu;
|
||||
49
src/components/layouts/Print/Header/ProfileOptionLogOut.jsx
Normal file
49
src/components/layouts/Print/Header/ProfileOptionLogOut.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import {Box, Button, MenuItem, Typography} from "@mui/material";
|
||||
import MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
|
||||
import useUser from "@/lib/app/hooks/useUser";
|
||||
import {useTranslations} from "next-intl";
|
||||
|
||||
export default function ProfileOptionLogOut({handleCloseUserMenu}) {
|
||||
const t = useTranslations();
|
||||
const {clearToken} = useUser();
|
||||
const handleClickLogOut = () => {
|
||||
handleCloseUserMenu();
|
||||
clearToken();
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<MenuItem
|
||||
component={Button}
|
||||
to={{
|
||||
pathname: "/dashboard/logout",
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
borderTop: 1,
|
||||
px: 3,
|
||||
py: 1.5,
|
||||
borderColor: "#e1e1e1",
|
||||
textTransform: "unset",
|
||||
}}
|
||||
onClick={handleClickLogOut}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
color: "primary.main",
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
<MeetingRoomIcon/>
|
||||
</Box>
|
||||
<Typography sx={{flex: 1}} textAlign="start">
|
||||
{t("header.logout")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
49
src/components/layouts/Print/Header/ProfileOptions.jsx
Normal file
49
src/components/layouts/Print/Header/ProfileOptions.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import {Box, MenuItem, Typography} from "@mui/material";
|
||||
import {NextLinkComposed} from "@/core/components/LinkRouting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import headerProfileItems from "@/core/data/headerProfileItems";
|
||||
import ProfileOptionLogOut from "./ProfileOptionLogOut";
|
||||
|
||||
export default function ProfileOptions({handleCloseUserMenu}) {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<>
|
||||
{headerProfileItems.map((profile_item) => (
|
||||
<MenuItem
|
||||
component={NextLinkComposed}
|
||||
to={{
|
||||
pathname: profile_item.route,
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
borderTop: 1,
|
||||
px: 3,
|
||||
py: 1.5,
|
||||
borderColor: "#e1e1e1",
|
||||
}}
|
||||
key={profile_item.key}
|
||||
onClick={handleCloseUserMenu}
|
||||
>
|
||||
<Box sx={{display: "flex", alignItems: "center", flex: 1}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
color: "primary.main",
|
||||
pr: 2,
|
||||
}}
|
||||
>
|
||||
{profile_item.icon}
|
||||
</Box>
|
||||
<Typography sx={{flex: 1}} textAlign="start">
|
||||
{t(profile_item.name)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
<ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
82
src/core/components/PrintablePage.jsx
Normal file
82
src/core/components/PrintablePage.jsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import {Box, Container, Divider, Grid, Paper, Stack, Typography} from '@mui/material';
|
||||
|
||||
const PrintablePage = ({children, header, footer}) => (
|
||||
<>
|
||||
<Box sx={{width: "100%", height: 8, displayPrint: 'none'}}/>
|
||||
<Container
|
||||
sx={{
|
||||
width: '21cm',
|
||||
minHeight: '29.7cm',
|
||||
margin: '0 auto',
|
||||
backgroundColor: 'white',
|
||||
p: '16px !important',
|
||||
pb: footer ? '84px!important' : '',
|
||||
position: 'relative'
|
||||
}}
|
||||
component="article" maxWidth="false">
|
||||
<Grid container columns={5} sx={{pt: 2, px: 4, display: header ? '' : 'none'}}>
|
||||
<Grid item xs={1}>
|
||||
<Box sx={{width: 70}}>
|
||||
<Box component={'img'} sx={{width: '100%', height: '100%', objectFit: 'contain'}}
|
||||
src={'/images/logo.png'}/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={3} sx={{textAlign: 'center'}}>
|
||||
<Typography sx={{fontFamily: 'Bnazanin'}}>باسمه تعالی</Typography>
|
||||
<Typography sx={{fontFamily: 'Bnazanin'}}>جمهوری اسلامی ایران</Typography>
|
||||
<Typography sx={{fontFamily: 'Bnazanin', fontWeight: 'bold'}}>وزارت راه و
|
||||
شهرسازی</Typography>
|
||||
<Typography sx={{fontFamily: 'Bnazanin', fontWeight: 'bold'}}>سازمان
|
||||
راهداری و حمل و نقل جاده
|
||||
ای</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={1}>
|
||||
<Stack>
|
||||
<Typography sx={{fontFamily: 'Bnazanin'}}>شماره:</Typography>
|
||||
<Typography sx={{fontFamily: 'Bnazanin'}}>تاریخ:</Typography>
|
||||
<Typography sx={{fontFamily: 'Bnazanin'}}>پیوست:</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Paper elevation={0} sx={{px: 8}}>
|
||||
{children}
|
||||
</Paper>
|
||||
<Box sx={{
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
px: 4,
|
||||
pb: 2,
|
||||
display: footer ? '' : 'none'
|
||||
}}>
|
||||
<Divider sx={{borderStyle: 'double', borderBottomWidth: 3, borderColor: '#000'}}/>
|
||||
<Stack sx={{my: .5}}>
|
||||
<Box sx={{textAlign: 'center'}}>
|
||||
<Typography variant={'caption'} fontWeight={'bold'} component={'span'}
|
||||
sx={{fontFamily: 'Bnazanin', px: 1}}> آدرس: تهران-بلوار
|
||||
کشاورز-خیابان فلسطین جنوبی-خیابان
|
||||
دمشق-پلاک17 </Typography>
|
||||
<Typography variant={'caption'} fontWeight={'bold'} component={'span'}
|
||||
sx={{fontFamily: 'Bnazanin', px: 1}}> تلفن: 88-88804379 </Typography>
|
||||
<Typography variant={'caption'} fontWeight={'bold'} component={'span'}
|
||||
sx={{fontFamily: 'Bnazanin', px: 1}}> تلفن گویا: 88804400 </Typography>
|
||||
<Typography variant={'caption'} fontWeight={'bold'} component={'span'}
|
||||
sx={{fontFamily: 'Bnazanin', px: 1}}> کدپستی: 1416753941 </Typography>
|
||||
</Box>
|
||||
<Box sx={{textAlign: 'center'}}>
|
||||
<Typography variant={'caption'} fontWeight={'bold'} component={'span'}
|
||||
sx={{fontFamily: 'Bnazanin', px: 2}}>صندوق پستی: 3773-14155</Typography>
|
||||
<Typography variant={'caption'} fontWeight={'bold'} component={'span'}
|
||||
sx={{fontFamily: 'Bnazanin', px: 2}}>پست الکترونیک: info@rmto.ir</Typography>
|
||||
<Typography variant={'caption'} fontWeight={'bold'} component={'span'}
|
||||
sx={{fontFamily: 'Bnazanin', px: 2}}>سایت الکترونیک: www.rmto.ir</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Container>
|
||||
<Box sx={{width: "100%", height: 8, displayPrint: 'none'}}/>
|
||||
</>
|
||||
);
|
||||
|
||||
export default PrintablePage;
|
||||
12
src/layouts/PrintLayout.jsx
Normal file
12
src/layouts/PrintLayout.jsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import WithAuthMiddleware from "@/middlewares/WithAuth";
|
||||
import Print from "@/components/layouts/Print";
|
||||
|
||||
const PrintLayout = (props) => {
|
||||
return (
|
||||
<WithAuthMiddleware>
|
||||
<Print {...props}/>
|
||||
</WithAuthMiddleware>
|
||||
)
|
||||
}
|
||||
|
||||
export default PrintLayout
|
||||
@@ -1,8 +1,10 @@
|
||||
import DashboardLayout from "@/layouts/DashboardLayout";
|
||||
import {Fragment} from "react";
|
||||
import PrintLayout from "@/layouts/PrintLayout";
|
||||
|
||||
const layoutList = {
|
||||
DashboardLayout
|
||||
DashboardLayout,
|
||||
PrintLayout
|
||||
}
|
||||
|
||||
const Layout = ({layout = {}, children}) => {
|
||||
|
||||
Reference in New Issue
Block a user