lab7 start (copied lab6)

This commit is contained in:
2026-04-14 11:08:41 +10:00
parent 4031d1497c
commit 400aca13a2
32 changed files with 4628 additions and 0 deletions

20
labs/lab7/src/App.tsx Normal file
View File

@@ -0,0 +1,20 @@
import NavBar from './components/Navbar'
import Gallery from "./components/Gallery";
import Content from "./components/Content";
import CustomFooter from "./components/CustomFooter";
import './styles/App.css'
function App() {
return (
<>
<NavBar active='2'/>
<Gallery/>
<Content/>
<CustomFooter/>
</>
)
}
export default App

View File

@@ -0,0 +1,53 @@
import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
import CardMedia from '@mui/material/CardMedia';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import { styled } from '@mui/material/styles';
interface ComponentProps {
building: {
img: string,
title: string,
description: string[]
},
cardNum: number;
}
const StyledTypography = styled(Typography)(({ theme }) => ({
color: theme.palette.text.secondary,
textAlign: 'justify',
marginBottom: '1em',
}));
function BuildCard({ building,cardNum} : ComponentProps) {
return (
<Card style={cardNum%2==0?{'flexDirection':'row-reverse'}:{}}sx={{ display: 'flex' }} >
<CardMedia
component="img"
alt={ building.title }
image={ building.img }
/>
<Box>
<CardContent>
<Typography gutterBottom variant="h5" >
{ building.title }
</Typography>
{ building.description.map((item, ind) => (
<StyledTypography key={ind} variant="body2">
{ item }
</StyledTypography>
))}
</CardContent>
<CardActions sx={{ justifyContent: cardNum%2!=0?'end':"start"}} >
<Button size="small">Подробнее</Button>
</CardActions>
</Box>
</Card>
)
}
export default BuildCard;

View File

@@ -0,0 +1,21 @@
import Container from '@mui/material/Container';
import Grid from '@mui/material/Grid';
import structures from "../data";
import BuildCard from "./BuildCard"
const cardData = [structures[3], structures[6], structures[9], structures[7]]
function Content() {
return (
<Container maxWidth="xl">
<Grid container spacing={{ xs: 3, md: 6 }}>
{cardData.map((item, index) => (
<Grid key={index} size={{ xs: 12, md: 6 }} >
<BuildCard building={ item } cardNum={index} />
</Grid>
))}
</Grid>
</Container>
);
}
export default Content;

View File

@@ -0,0 +1,26 @@
import Container from '@mui/material/Container';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import { styled } from '@mui/material/styles';
const StyledContainer = styled(Container)(({ theme }) => ({
backgroundColor: theme.palette.action.hover,
borderRadius: `calc(${theme.shape.borderRadius}px + 8px)`,
marginTop: "50px",
padding: "20px",
color: theme.palette.text.secondary
}));
function CustomFooter() {
return (
<StyledContainer >
<Grid style={{ justifyContent: "space-around",}} container>
<Typography> OkunElya</Typography>
<Typography> 2026</Typography>
<Typography> FEFU</Typography>
</Grid>
</StyledContainer>
);
}
export default CustomFooter;

View File

@@ -0,0 +1,41 @@
import ImageList from '@mui/material/ImageList';
import ImageListItem from '@mui/material/ImageListItem';
import structures from "../data";
import Box from '@mui/material/Box';
import Container from '@mui/material/Container';
import ImageListItemBar from '@mui/material/ImageListItemBar';
const imgData = structures.slice(0, -1);
function Gallery() {
return (
<Container maxWidth="lg">
<Box sx={{ width: 800, height: 585, overflowY: 'scroll', m: '20px auto' }}>
<ImageList
variant="masonry"
sx={{
columnCount: {
xs: '1 !important',
sm: '2 !important',
md: '3 !important',
lg: '4 !important',
},
}}
gap={8}>
{imgData.map((item) => (
<ImageListItem key={item.img}>
<img
srcSet={item.img}
src={item.img}
alt={item.title}
loading="lazy"
/>
<ImageListItemBar position="bottom" title={ item.title } />
</ImageListItem>
))}
</ImageList>
</Box>
</Container>
);
}
export default Gallery;

View File

@@ -0,0 +1,105 @@
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import { styled } from '@mui/material/styles';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import MenuItem from '@mui/material/MenuItem';
import Drawer from '@mui/material/Drawer';
import MenuIcon from '@mui/icons-material/Menu';
import MenuList from '@mui/material/MenuList';
import { useState } from 'react';
const StyledToolbar = styled(Toolbar)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
flexShrink: 0,
borderRadius: `calc(${theme.shape.borderRadius}px + 8px)`,
border: '1px solid',
borderColor: theme.palette.divider,
padding: '8px 12px',
}));
const StyledMenuItem =styled(MenuItem)(({}) => ({
'&.Mui-selected': {
backgroundColor: '#1976d2',
color: "white",
},
'&.Mui-selected:hover': {
backgroundColor: '#11579c',
color: "white",
},
'&:hover': {
backgroundColor: 'rgba(69, 146, 223, 0.45)',
},
}));
interface ComponentProps {
active: string;
}
function NavBar({ active }: ComponentProps) {
const [open, setOpen] = useState(false);
const toggleDrawer = (newOpen: boolean) => () => {
setOpen(newOpen);
};
return (
<AppBar
position="static"
sx={{
boxShadow: 0,
bgcolor: 'transparent',
mt: '28px',
}}
>
<Container maxWidth="xl">
<StyledToolbar>
<Typography variant="h6" sx={{ color: '#5d8aa8' }}>
Самые высокие здания и сооружения
</Typography>
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
<Button variant={active == '1' ? 'contained' : 'text'} color="info" size="medium">
Главная
</Button>
<Button variant={active == '2' ? 'contained' : 'text'} color="info" size="medium">
Список зданий
</Button>
<Button variant={active == '3' ? 'contained' : 'text'} color="info" size="medium">
Контакты
</Button>
</Box>
<Box sx={{ display: { xs: 'flex', md: 'none' } }}>
<IconButton aria-label="Menu button" onClick={toggleDrawer(true)}>
<MenuIcon />
</IconButton>
<Drawer
anchor="top"
open={open}
onClose={toggleDrawer(false)}
>
<Box>
<IconButton onClick={toggleDrawer(false)}>
<CloseRoundedIcon />
</IconButton>
</Box>
<MenuList>
<StyledMenuItem selected={active == '1'}> Главная </StyledMenuItem>
<StyledMenuItem selected={active == '2'}>Список зданий</StyledMenuItem>
<StyledMenuItem selected={active == '3'}>Контакты</StyledMenuItem>
</MenuList>
</Drawer>
</Box>
</StyledToolbar>
</Container>
</AppBar>
);
}
export default NavBar;

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.0 KiB

10
labs/lab7/src/main.tsx Normal file
View File

@@ -0,0 +1,10 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './styles/index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)

View File

@@ -0,0 +1,184 @@
.counter {
font-size: 16px;
padding: 5px 10px;
border-radius: 5px;
color: var(--accent);
background: var(--accent-bg);
border: 2px solid transparent;
transition: border-color 0.3s;
margin-bottom: 24px;
&:hover {
border-color: var(--accent-border);
}
&:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
}
.hero {
position: relative;
.base,
.framework,
.vite {
inset-inline: 0;
margin: 0 auto;
}
.base {
width: 170px;
position: relative;
z-index: 0;
}
.framework,
.vite {
position: absolute;
}
.framework {
z-index: 1;
top: 34px;
height: 28px;
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
scale(1.4);
}
.vite {
z-index: 0;
top: 107px;
height: 26px;
width: auto;
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
scale(0.8);
}
}
#center {
display: flex;
flex-direction: column;
gap: 25px;
place-content: center;
place-items: center;
flex-grow: 1;
@media (max-width: 1024px) {
padding: 32px 20px 24px;
gap: 18px;
}
}
#next-steps {
display: flex;
border-top: 1px solid var(--border);
text-align: left;
& > div {
flex: 1 1 0;
padding: 32px;
@media (max-width: 1024px) {
padding: 24px 20px;
}
}
.icon {
margin-bottom: 16px;
width: 22px;
height: 22px;
}
@media (max-width: 1024px) {
flex-direction: column;
text-align: center;
}
}
#docs {
border-right: 1px solid var(--border);
@media (max-width: 1024px) {
border-right: none;
border-bottom: 1px solid var(--border);
}
}
#next-steps ul {
list-style: none;
padding: 0;
display: flex;
gap: 8px;
margin: 32px 0 0;
.logo {
height: 18px;
}
a {
color: var(--text-h);
font-size: 16px;
border-radius: 6px;
background: var(--social-bg);
display: flex;
padding: 6px 12px;
align-items: center;
gap: 8px;
text-decoration: none;
transition: box-shadow 0.3s;
&:hover {
box-shadow: var(--shadow);
}
.button-icon {
height: 18px;
width: 18px;
}
}
@media (max-width: 1024px) {
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
li {
flex: 1 1 calc(50% - 8px);
}
a {
width: 100%;
justify-content: center;
box-sizing: border-box;
}
}
}
#spacer {
height: 88px;
border-top: 1px solid var(--border);
@media (max-width: 1024px) {
height: 48px;
}
}
.ticks {
position: relative;
width: 100%;
&::before,
&::after {
content: '';
position: absolute;
top: -4.5px;
border: 5px solid transparent;
}
&::before {
left: 0;
border-left-color: var(--border);
}
&::after {
right: 0;
border-right-color: var(--border);
}
}

View File

@@ -0,0 +1,111 @@
:root {
--text: #6b6375;
--text-h: #08060d;
--bg: #fff;
--border: #e5e4e7;
--code-bg: #f4f3ec;
--accent: #aa3bff;
--accent-bg: rgba(170, 59, 255, 0.1);
--accent-border: rgba(170, 59, 255, 0.5);
--social-bg: rgba(244, 243, 236, 0.5);
--shadow:
rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
--sans: system-ui, 'Segoe UI', Roboto, sans-serif;
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
--mono: ui-monospace, Consolas, monospace;
font: 18px/145% var(--sans);
letter-spacing: 0.18px;
color-scheme: light dark;
color: var(--text);
background: var(--bg);
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@media (max-width: 1024px) {
font-size: 16px;
}
}
@media (prefers-color-scheme: dark) {
:root {
--text: #9ca3af;
--text-h: #f3f4f6;
--bg: #16171d;
--border: #2e303a;
--code-bg: #1f2028;
--accent: #c084fc;
--accent-bg: rgba(192, 132, 252, 0.15);
--accent-border: rgba(192, 132, 252, 0.5);
--social-bg: rgba(47, 48, 58, 0.5);
--shadow:
rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
}
#social .button-icon {
filter: invert(1) brightness(2);
}
}
#root {
width: 1126px;
max-width: 100%;
margin: 0 auto;
text-align: center;
border-inline: 1px solid var(--border);
min-height: 100svh;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
body {
margin: 0;
}
h1,
h2 {
font-family: var(--heading);
font-weight: 500;
color: var(--text-h);
}
h1 {
font-size: 56px;
letter-spacing: -1.68px;
margin: 32px 0;
@media (max-width: 1024px) {
font-size: 36px;
margin: 20px 0;
}
}
h2 {
font-size: 24px;
line-height: 118%;
letter-spacing: -0.24px;
margin: 0 0 8px;
@media (max-width: 1024px) {
font-size: 20px;
}
}
p {
margin: 0;
}
code,
.counter {
font-family: var(--mono);
display: inline-flex;
border-radius: 4px;
color: var(--text-h);
}
code {
font-size: 15px;
line-height: 135%;
padding: 4px 8px;
background: var(--code-bg);
}