Repository: nikolay-klekto/fs-platform-ru
Pull request #210: Ff 151 companies page mobi
Author: login: TaisNch
Created: 2025-05-07T15:54:17Z | Merged: 2025-05-17T20:28:22Z

Создана страница компании в мобильной версии, селектор работает по отраслям, есть поиск по наименованию компаний:
![Снимок экрана 2025-05-07 175122](https://github.com/user-attachments/assets/09cd5f7a-1fda-4de3-8f36-bfe5507abb4e)
![Снимок экрана 2025-05-07 175135](https://github.com/user-attachments/assets/fd298e72-e0c5-419c-bf7a-a2935a125b4d)
![Снимок экрана 2025-05-07 175213](https://github.com/user-attachments/assets/039e607f-a994-479f-9d7b-df8778561e52)



Diff:
diff --git a/frontend-react/app/companies/page.tsx b/frontend-react/app/companies/page.tsx
index b5c794c0a..69e0e127d 100644
--- a/frontend-react/app/companies/page.tsx
+++ b/frontend-react/app/companies/page.tsx
@@ -2,7 +2,7 @@
 
 import { useState, useEffect } from 'react'
 import { useMediaQuery } from 'react-responsive'
-
+import CompaniesPageMobi from '@/components/mobi/pageMobi/CompaniesPageMobi/CompaniesPageMobi'
 export default function Companies() {
     const [isClient, setIsClient] = useState(false)
 
@@ -11,7 +11,7 @@ export default function Companies() {
     }, [])
 
     const isDesktop = useMediaQuery({
-        query: '(min-width: 768px)',
+        query: '(min-width: 1240px)',
     })
 
     if (!isClient) {
@@ -27,9 +27,7 @@ export default function Companies() {
                 </>
             ) : (
                 <>
-                    <main className="bg-[#101030] text-white">
-                        <h1>Companies</h1>
-                    </main>
+                    <CompaniesPageMobi />
                 </>
             )}
         </div>
diff --git a/frontend-react/components/mobi/layout/HeaderMobi/ItemHeaderMobi/contentHeaderNavigationMobi/content.tsx b/frontend-react/components/mobi/layout/HeaderMobi/ItemHeaderMobi/contentHeaderNavigationMobi/content.tsx
index 379f13823..a5da63f5c 100644
--- a/frontend-react/components/mobi/layout/HeaderMobi/ItemHeaderMobi/contentHeaderNavigationMobi/content.tsx
+++ b/frontend-react/components/mobi/layout/HeaderMobi/ItemHeaderMobi/contentHeaderNavigationMobi/content.tsx
@@ -15,11 +15,11 @@ export const content: IHeaderNavigation[] = [
         link: '/professions',
         id: '2',
     },
-    /* {
+    {
         title: 'Компании',
         link: '/companies',
         id: '3',
-    },*/
+    },
     {
         title: 'Личный профиль',
         link: '/profile',
diff --git a/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/CompaniesPageMobi.tsx b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/CompaniesPageMobi.tsx
new file mode 100644
index 000000000..f155b7909
--- /dev/null
+++ b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/CompaniesPageMobi.tsx
@@ -0,0 +1,117 @@
+'use client'
+import React, { useEffect, useState } from 'react'
+import CompaniesCardPageMobi from './components/CompaniesCardPageMobi'
+import CompaniesPaginationMobi from './components/CompaniesPaginationMobi'
+import CompaniesSendMobi from './components/CompaniesSendMobi'
+import { content } from './contentCompaniesPageMobi/content'
+import { EnhancedInput } from '@/components/ui/input'
+import { Button } from '@/components/ui/button'
+import { Search } from 'lucide-react'
+import { useModal } from '@/context/ContextModal'
+import CompaniesSelectMobi from './components/CompaniesSelectMobi'
+import HeaderMobi from '@/components/mobi/layout/HeaderMobi/HeaderMobi'
+import FooterMobi from '@/components/mobi/layout/FooterMobi/FooterMobi'
+
+const CompaniesPageMobi: React.FC = () => {
+    const { openModal } = useModal()
+    const [searchQuery, setSearchQuery] = useState('')
+    const [currentPage, setCurrentPage] = useState(1)
+    const [selectedCategories, setSelectedCategories] = useState<string[]>([])
+    const cardsPerPage = 6
+
+    const filteredContent = content.filter((item) => {
+        const matchesSearch =
+            searchQuery.length < 3 || item.companyName.toLowerCase().includes(searchQuery.toLowerCase().trim())
+        const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(item.industry)
+        return matchesSearch && matchesCategory
+    })
+
+    const totalPages = Math.ceil(filteredContent.length / cardsPerPage)
+    const safeCurrentPage = Math.min(currentPage, totalPages || 1)
+
+    const handleCategoryChange = (categories: string[]) => {
+        setSelectedCategories(categories)
+    }
+
+    const handlePageChange = (page: number): void => {
+        setCurrentPage(page)
+    }
+
+    useEffect(() => {
+        const newTotalPages = Math.ceil(filteredContent.length / cardsPerPage)
+        if (currentPage > newTotalPages) {
+            setCurrentPage(1)
+        }
+    }, [currentPage, filteredContent])
+
+    return (
+        <>
+            <div className="h-[20px] bg-[#101030]">
+                <HeaderMobi />
+                <main className="bg-[#101030] text-white">
+                    <div className="px-[15px] py-[40px]">
+                        <h1 className="title28px_mobi_custom">Компании</h1>
+                        <div className="flex items-center gap-[21px] py-[30px]">
+                            <div className="relative w-full max-w-[282px]">
+                                <div className="relative rounded-[50px] bg-transparent p-[2.5px] transition">
+                                    <EnhancedInput
+                                        type="text"
+                                        value={searchQuery}
+                                        onChange={setSearchQuery}
+                                        variant={'search_mobi'}
+                                        size={'search_companies_mobi'}
+                                        rounded={'full'}
+                                        wrapperClassName={
+                                            'relative h-[48px] border-[2px] border-[#878797] bg-[#101030] flex-1 justify-bitween flex rounded-[50px]'
+                                        }
+                                        placeholder="Поиск"
+                                    />
+                                </div>
+                                <Button variant="circle_btn_mobi" size="circle_btn_mobi">
+                                    <Search color="#878797" width={24} height={24} strokeWidth={2} />
+                                </Button>
+                            </div>
+                            <CompaniesSelectMobi onCategoryChange={handleCategoryChange} />
+                        </div>
+                        {filteredContent.length > 0 ? (
+                            <>
+                                <div className="flex flex-wrap justify-center gap-[20px] sm_xl:gap-[15px]">
+                                    {filteredContent
+                                        .slice((safeCurrentPage - 1) * cardsPerPage, currentPage * cardsPerPage)
+                                        .map((item) => (
+                                            <CompaniesCardPageMobi
+                                                key={item.id}
+                                                image={item.image}
+                                                industry={item.industry}
+                                                price={item.price.toString()}
+                                                // здесь будет открываться страница компании, пока оставлена ссылка на профессии
+                                                onClick={() => {
+                                                    openModal('profession_modal_mobi', 'mobi', {
+                                                        profession: item.companyName,
+                                                        professionId: item.id,
+                                                    })
+                                                }}
+                                                companyName={item.companyName}
+                                            />
+                                        ))}
+                                </div>
+                                {totalPages >= 1 && (
+                                    <CompaniesPaginationMobi
+                                        totalPages={totalPages}
+                                        currentPage={safeCurrentPage}
+                                        onPageChange={handlePageChange}
+                                    />
+                                )}
+                            </>
+                        ) : (
+                            <p className="my-16 min-h-[60px] text-center text-xl text-white">Ничего не найдено</p>
+                        )}
+                        <CompaniesSendMobi />
+                    </div>
+                </main>
+                <FooterMobi />
+            </div>
+        </>
+    )
+}
+export default CompaniesPageMobi
diff --git a/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesCardPageMobi.tsx b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesCardPageMobi.tsx
new file mode 100644
index 000000000..4d77a1e22
--- /dev/null
+++ b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesCardPageMobi.tsx
@@ -0,0 +1,54 @@
+'use client'
+
+import React from 'react'
+import { Card, CardTitle, CardContent, CardFooter } from '@/components/ui/card'
+
+interface IProfessionCard {
+    companyName: string
+    image: string
+    price: string
+    industry?: string
+    onClick: () => void
+}
+
+const ProfessionCardPageMobi: React.FC<IProfessionCard> = ({ image, companyName, price, industry, onClick }) => {
+    return (
+        <>
+            <div className="relative overflow-hidden rounded-[10px]">
+                <div
+                    className="absolute inset-0 z-0 rounded-[10px] bg-center opacity-80"
+                    style={{ backgroundImage: `url(${image})`, backgroundSize: '150%', backgroundPosition: 'center' }}
+                />
+                <Card
+                    variant={'companies_page_mobi'}
+                    size={'companies_page_mobi'}
+                    rounded="rounded_10"
+                    className="z-5 relative"
+                    onClick={onClick}
+                >
+                    <CardTitle variant={'companies_page_mobi'} size={'companies_page_mobi'}>
+                        {industry}
+                    </CardTitle>
+                    <CardContent className="font-semibold flex grow items-end p-0 px-[4px] text-2xl text-white 2xl:text-base 3xl:text-lg 4xl:text-xl">
+                        {companyName}
+                    </CardContent>
+
+                    <CardFooter variant={'companies_page_mobi'} size={'companies_page_mobi'} rounded={'rounded_12'}>
+                        <p
+                            className="3xl:sm text-lg tracking-normal text-[#878797]
+                    2xl:text-xs  4xl:text-base"
+                        >
+                            от{' '}
+                            <span className="w-fit bg-gradient-mobi bg-clip-text  text-xl text-transparent">
+                                {price} BYN/
+                            </span>
+                            неделя
+                        </p>
+                    </CardFooter>
+                </Card>
+            </div>
+        </>
+    )
+}
+
+export default ProfessionCardPageMobi
diff --git a/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesPaginationMobi.tsx b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesPaginationMobi.tsx
new file mode 100644
index 000000000..1fffe0f92
--- /dev/null
+++ b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesPaginationMobi.tsx
@@ -0,0 +1,70 @@
+'use client'
+
+import React, { useEffect, useState } from 'react'
+import { LessIconMobi, MoreIconMobi } from '@/components/assets/iconsMobi'
+
+interface IProfessionsPagination {
+    totalPages: number
+    currentPage: number
+    onPageChange: (page: number) => void
+}
+
+const ProfessionsPaginationMobi: React.FC<IProfessionsPagination> = ({ totalPages, currentPage, onPageChange }) => {
+    const [visibleStart, setVisibleStart] = useState(1)
+    const visibleEnd = visibleStart + 2
+
+    const handleLessClick = () => {
+        if (visibleStart > 1) {
+            setVisibleStart(visibleStart - 1)
+            onPageChange(visibleStart - 1)
+        }
+    }
+    const handleMoreClick = () => {
+        if (visibleEnd < totalPages) {
+            setVisibleStart(visibleStart + 1)
+            onPageChange(visibleStart + 1)
+        }
+    }
+
+    useEffect(() => {
+        if (currentPage < visibleStart || currentPage > visibleStart + 2) {
+            setVisibleStart(Math.min(1, currentPage - 1))
+        }
+    }, [currentPage, visibleStart])
+
+    return (
+        <div className="mx-auto mb-[30px] mt-[25px] flex w-[150px] items-center justify-between">
+            <LessIconMobi
+                width={'10'}
+                height={'19'}
+                className={visibleStart === 1 ? 'text-[#878797]' : 'text-[#FFFFFFCC]'}
+                onClick={visibleStart > 1 ? handleLessClick : undefined}
+            />
+
+            {[...Array(totalPages)]
+                .map((_, index) => index + 1)
+                .filter((pageNumber) => pageNumber >= visibleStart && pageNumber <= visibleEnd)
+                .map((pageNumber) => {
+                    return (
+                        <button
+                            key={pageNumber}
+                            className={`text-5xl font-medium ${
+                                currentPage === pageNumber ? 'text-gradient_mobi_custom' : 'text-[#FFFFFFCC]'
+                            }`}
+                            onClick={() => onPageChange(pageNumber)}
+                        >
+                            {pageNumber}
+                        </button>
+                    )
+                })}
+            <MoreIconMobi
+                width={'10'}
+                height={'19'}
+                className={visibleEnd >= totalPages ? 'text-[#878797]' : 'text-[#FFFFFFCC]'}
+                onClick={visibleEnd < totalPages ? handleMoreClick : undefined}
+            />
+        </div>
+    )
+}
+
+export default ProfessionsPaginationMobi
diff --git a/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesSelectMobi.tsx b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesSelectMobi.tsx
new file mode 100644
index 000000000..91d36d4ae
--- /dev/null
+++ b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesSelectMobi.tsx
@@ -0,0 +1,172 @@
+'use client'
+import React, { useState, useEffect, useRef } from 'react'
+import { CheckedBoxIconMobi, FiltersIconMobi } from '@/components/assets/iconsMobi'
+
+interface ISelectItem {
+    value: string
+    children: React.ReactNode
+    isChecked: boolean
+    onClick: () => void
+}
+
+interface ISelectOption {
+    value: string
+    label: string
+}
+
+const ProfessionsSelectMobi = ({ onCategoryChange }: { onCategoryChange: (categories: string[]) => void }) => {
+    const [isOpen, setIsOpen] = useState(false)
+    const [selectedOptions, setSelectedOptions] = useState<string[]>([])
+    const selectRef = useRef<HTMLDivElement>(null)
+
+    const toggleOption = (value: string) => {
+        setSelectedOptions((prev) =>
+            prev.includes(value) ? prev.filter((option) => option !== value) : [...prev, value],
+        )
+    }
+
+    const handleSelectToggle = () => {
+        setIsOpen((prev) => !prev)
+    }
+
+    useEffect(() => {
+        onCategoryChange(selectedOptions)
+    }, [selectedOptions, onCategoryChange])
+
+    const options: ISelectOption[] = [
+        { value: 'IT-компания', label: 'IT-компания' },
+        { value: 'Здравоохранение', label: 'Здравоохранение' },
+        { value: 'Искусство', label: 'Искусство' },
+        { value: 'Спорт', label: 'Спорт' },
+        { value: 'field5', label: 'Отрасль 5' },
+        { value: 'field6', label: 'Отрасль 6' },
+        { value: 'field7', label: 'Отрасль 7' },
+    ]
+
+    const [isFilterActive, setIsFilterActive] = useState(false)
+
+    const handleFilterIconClick = () => {
+        setIsFilterActive(!isFilterActive)
+    }
+
+    const clearSelection = () => {
+        setSelectedOptions([])
+    }
+
+    useEffect(() => {
+        const handleClickOutside = (event: MouseEvent) => {
+            if (selectRef.current && !selectRef.current.contains(event.target as Node)) {
+                setIsOpen(false)
+                setIsFilterActive(false)
+            }
+        }
+
+        document.addEventListener('mousedown', handleClickOutside)
+
+        return () => {
+            document.removeEventListener('mousedown', handleClickOutside)
+        }
+    }, [])
+
+    return (
+        <div className="relative z-[3]">
+            <FiltersIconMobi
+                className={`size-[32px] ${isFilterActive ? 'text-white' : 'text-[#878797]'}`}
+                onClick={() => {
+                    handleFilterIconClick()
+                    handleSelectToggle()
+                }}
+            />
+            {isOpen && (
+                <div className="fixed inset-0 z-50" style={{ background: 'rgba(0, 0, 0, 0.7)' }}>
+                    <div className="fixed left-0 top-0 z-50 w-full rounded-[40px] ">
+                        <div
+                            className="flex flex-col rounded-b-[40px] bg-[#1F203F] px-[14px] pb-[50px] pt-[18px] "
+                            ref={selectRef}
+                        >
+                            <div className="mb-[33px] mt-[10px] flex items-center justify-between text-white">
+                                <span className="text-3xl font-semibold">Выберите отрасль</span>
+                                <button className="text-base text-[#878797] underline" onClick={clearSelection}>
+                                    Очистить
+                                </button>
+                            </div>
+                            <div className="flex max-h-[325px] flex-col overflow-y-auto scroll-smooth pr-1">
+                                {options.map((option) => (
+                                    <SelectItem
+                                        key={option.value}
+                                        value={option.value}
+                                        isChecked={selectedOptions.includes(option.value)}
+                                        onClick={() => toggleOption(option.value)}
+                                    >
+                                        {option.label}
+                                    </SelectItem>
+                                ))}
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            )}
+        </div>
+    )
+}
+
+const SelectItem = React.forwardRef<HTMLDivElement, ISelectItem>(
+    ({ children, isChecked, onClick, ...props }, forwardedRef) => {
+        return (
+            <div className="pt-[2px]">
+                <div
+                    className={`text-15px text-medium relative z-[3] flex cursor-pointer items-center px-[16px] py-[14px] ${
+                        isChecked
+                            ? 'h-[51px] rounded-[18px] bg-[#5F4AF30F] py-[14px] text-white'
+                            : 'bg-transparent text-[#878797]'
+                    }`}
+                    {...props}
+                    ref={forwardedRef}
+                    onClick={onClick}
+                    role="menuitem"
+                    tabIndex={0}
+                    onKeyDown={(e) => {
+                        if (e.key === 'Enter' || e.key === ' ') {
+                            e.preventDefault()
+                            onClick()
+                        }
+                    }}
+                >
+                    <div className="relative flex size-[20px] items-center justify-center">
+                        <input
+                            type="checkbox"
+                            checked={isChecked}
+                            onChange={(e) => {
+                                e.stopPropagation()
+                                onClick()
+                            }}
+                            className="absolute inset-0 size-full cursor-pointer opacity-0"
+                        />
+                        {isChecked ? (
+                            <CheckedBoxIconMobi
+                                style={{
+                                    position: 'absolute',
+                                    width: '30px',
+                                    height: '25px',
+                                }}
+                            />
+                        ) : (
+                            <div
+                                className="absolute inset-0 z-[3] rounded-[3px]"
+                                style={{
+                                    border: '2px solid #878797',
+                                    background: 'transparent',
+                                }}
+                            ></div>
+                        )}
+                    </div>
+                    <div className="pl-[20px]">{children}</div>
+                </div>
+            </div>
+        )
+    },
+)
+
+SelectItem.displayName = 'SelectItem'
+
+export default ProfessionsSelectMobi
diff --git a/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesSendMobi.tsx b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesSendMobi.tsx
new file mode 100644
index 000000000..28775765b
--- /dev/null
+++ b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/components/CompaniesSendMobi.tsx
@@ -0,0 +1,35 @@
+import React, { useState } from 'react'
+import { EnhancedInput } from '@/components/ui/input'
+import { SendIconMobi } from '@/components/assets/iconsMobi'
+
+const ProfessionSendMobi: React.FC = () => {
+    const [useRequest, setUseRequest] = useState('')
+
+    const handleSendRequest = () => {
+        console.log('Отправка запроса на профессию:', useRequest)
+        setUseRequest('')
+    }
+    return (
+        <div className="flex flex-col gap-[17px]">
+            <div className="text-[14px] font-medium uppercase  md:text-center">
+                <p>Хотите поработать в другой компании?</p>
+                <p>Дайте нам знать!</p>
+            </div>
+            <div className="justify-bitween mx-auto flex h-[34px] w-full max-w-[400px] items-center gap-[15px]">
+                <div className="relative size-full rounded-[20px] bg-transparent p-[1.3px] transition">
+                    <EnhancedInput
+                        type="text"
+                        value={useRequest}
+                        onChange={(value) => setUseRequest(value)}
+                        variant={'search_mobi'}
+                        size={'send_mobi'}
+                        rounded={'rounded_20'}
+                        wrapperClassName="justify-bitween h-[30px] rounded-[20px] border-box w-full border-[1.25px] bg-[#101030] border-[#878797]"
+                    />
+                </div>
+                <SendIconMobi onClick={handleSendRequest} />
+            </div>
+        </div>
+    )
+}
+export default ProfessionSendMobi
diff --git a/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/contentCompaniesPageMobi/content.tsx b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/contentCompaniesPageMobi/content.tsx
new file mode 100644
index 000000000..29374d04d
--- /dev/null
+++ b/frontend-react/components/mobi/pageMobi/CompaniesPageMobi/contentCompaniesPageMobi/content.tsx
@@ -0,0 +1,211 @@
+interface ICompanyContent {
+    companyName: string
+    industry: string
+    image: string
+    price: number
+    id: number
+}
+
+export const content: ICompanyContent[] = [
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 120,
+        id: 1,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 125,
+        id: 2,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 130,
+        id: 3,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 110,
+        id: 4,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 140,
+        id: 5,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 135,
+        id: 6,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 128,
+        id: 7,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 122,
+        id: 8,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 127,
+        id: 9,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 133,
+        id: 10,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 138,
+        id: 11,
+    },
+    {
+        companyName: 'EPAM Systems',
+        industry: 'IT-компания',
+        image: '/images/epam.png',
+        price: 129,
+        id: 12,
+    },
+
+    {
+        companyName: 'Наименование компании',
+        industry: 'Здравоохранение',
+        image: '/images/profession_1.jpg',
+        price: 100,
+        id: 13,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Здравоохранение',
+        image: '/images/profession_1.jpg',
+        price: 105,
+        id: 14,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Здравоохранение',
+        image: '/images/profession_1.jpg',
+        price: 95,
+        id: 15,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Здравоохранение',
+        image: '/images/profession_1.jpg',
+        price: 102,
+        id: 16,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Здравоохранение',
+        image: '/images/profession_1.jpg',
+        price: 98,
+        id: 17,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Здравоохранение',
+        image: '/images/profession_1.jpg',
+        price: 106,
+        id: 18,
+    },
+
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 80,
+        id: 19,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 85,
+        id: 20,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 75,
+        id: 21,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 88,
+        id: 22,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 82,
+        id: 23,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 86,
+        id: 24,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 90,
+        id: 25,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 87,
+        id: 26,
+    },
+    {
+        companyName: 'Наименование компании',
+        industry: 'Искусство',
+        image: '/images/profession_2.jpg',
+        price: 84,
+        id: 27,
+    },
+
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 92, id: 28 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 95, id: 29 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 90, id: 30 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 94, id: 31 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 89, id: 32 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 91, id: 33 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 93, id: 34 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 97, id: 35 },
+    { companyName: 'Наименование компании', industry: 'Спорт', image: '/images/profession_3.jpg', price: 96, id: 36 },
+]
diff --git a/frontend-react/components/ui/card.tsx b/frontend-react/components/ui/card.tsx
index fc98c3997..b648c7379 100644
--- a/frontend-react/components/ui/card.tsx
+++ b/frontend-react/components/ui/card.tsx
@@ -13,24 +13,29 @@ const cardVariants = cva('border-none', {
             profession_page_desktop:
                 'hover:button-shadow_around_desktop_custom relative flex cursor-pointer flex-col justify-between border-none bg-cover bg-center',
             profession_page_mobi: 'flex flex-col justify-between border-none bg-cover bg-center bg-no-repeat',
+            companies_page_mobi: 'flex flex-col justify-between border-none bg-cover bg-center bg-no-repeat',
         },
         size: {
             default: '',
             profession_home_desktop:
-                '3xl:px-[20px] 3xl:py-[15px] aspect-[426/520] px-[30px] py-[20px] 2xl:px-[15px] 2xl:py-[10px]',
+                'aspect-[426/520] px-[30px] py-[20px] 2xl:px-[15px] 2xl:py-[10px] 3xl:px-[20px] 3xl:py-[15px]',
             profession_home_mobi:
-                'sm_xl:w-[320px] sm_l:w-[300px] sm_s:w-[280px] aspect-[5/6] w-[320px] p-[20px] sm:w-[260px]',
+                'aspect-[5/6] w-[320px] p-[20px] sm:w-[260px] sm_s:w-[280px] sm_l:w-[300px] sm_xl:w-[320px]',
             profession_page_desktop:
                 'aspect-[340/400] w-[340px] max-w-full  px-[20px] py-[25px] 2xl:px-[15px] 2xl:py-[20px]',
             profession_page_mobi:
                 'aspect-[164/193] w-[164px] max-w-[210px] flex-shrink flex-grow overflow-hidden rounded-[24px] px-[10px] py-[12px] md:aspect-[164/193] md:w-[185px]',
+            companies_page_mobi:
+                'aspect-[165/193] w-[165px] max-w-[210px] flex-shrink flex-grow overflow-hidden rounded-[10px] p-[10px] md:aspect-[164/193] md:w-[185px]',
         },
+
         rounded: {
             default: 'rounded-[50px]',
             none: 'rounded-none',
             full: 'rounded-full',
             rounded_38: 'rounded-[38px]',
             rounded_24: 'rounded-[24px]',
+            rounded_10: 'rounded-[10px]',
         },
     },
     defaultVariants: {
@@ -49,16 +54,18 @@ const cardTitleVariants = cva('font-medium', {
             profession_home_mobi:
                 'text22px_mobi bg-white bg-opacity-[70%] font-semibold tracking-normal text-[#101030]',
             profession_page_desktop:
-                '4xl:text-6xl 3xl:text-5xl truncate bg-white bg-opacity-[70%] text-7xl font-medium text-[#101030] 2xl:text-4xl',
+                'truncate bg-white bg-opacity-[70%] text-7xl font-medium text-[#101030] 2xl:text-4xl 3xl:text-5xl 4xl:text-6xl',
             profession_page_mobi: 'bg-white bg-opacity-[70%] text-[13px] font-medium text-[#101030]',
+            companies_page_mobi: 'text-[10px] font-semibold text-white',
         },
         size: {
             default: 'text-[24px]',
             profession_home_desktop: 'w-fit px-[20px] py-[10px]',
             profession_home_mobi: 'w-fit px-[15px] py-[10px] ',
             profession_page_desktop:
-                '3xl:px-[15px] 4xl:px-[15px] 4xl:max-w-full w-fit max-w-full  rounded-[25px] px-[20px] py-[2px] 2xl:px-[10px]',
+                'w-fit max-w-full rounded-[25px] px-[20px] py-[2px]  2xl:px-[10px] 3xl:px-[15px] 4xl:max-w-full 4xl:px-[15px]',
             profession_page_mobi: 'w-fit max-w-full truncate px-[10px] py-[3px]',
+            companies_page_mobi: 'w-fit max-w-full truncate',
         },
         rounded: {
             default: 'rounded-[50px]',
@@ -85,14 +92,16 @@ const cardFooterVariants = cva('p-0', {
             profession_home_mobi: 'bg-white bg-opacity-[100%] font-medium',
             profession_page_desktop: 'whitespace-nowrap bg-white font-medium',
             profession_page_mobi: 'whitespace-nowrap bg-white font-medium',
+            companies_page_mobi: 'whitespace-nowrap bg-white font-medium',
         },
         size: {
             default: '',
             profession_home_desktop: 'w-fit px-[15px] py-[5px] pb-3 2xl:px-[10px]',
             profession_home_mobi: 'w-fit px-[15px] py-[5px]',
             profession_page_desktop:
-                '4xl:px-[15px] 3xl:px-[15px] 4xl:py-[4px] 3xl:py-[2px] w-fit px-[20px] py-[5px] 2xl:px-[10px] 2xl:py-0',
+                'w-fit px-[20px] py-[5px] 2xl:px-[10px] 2xl:py-0 3xl:px-[15px] 3xl:py-[2px] 4xl:px-[15px] 4xl:py-[4px]',
             profession_page_mobi: 'w-fit px-[10px] py-[2px]',
+            companies_page_mobi: 'w-fit px-[8px] py-[2px]',
         },
         rounded: {
             default: 'rounded-[50px]',
diff --git a/frontend-react/components/ui/input.tsx b/frontend-react/components/ui/input.tsx
index 638ad6af2..e8e380ffc 100644
--- a/frontend-react/components/ui/input.tsx
+++ b/frontend-react/components/ui/input.tsx
@@ -29,7 +29,8 @@ const inputVariants = cva(
                 default: 'h-10 px-3 py-2',
                 gradient_search_desktop: 'size-full py-[20px] pl-[20px] pr-[70px]',
                 gradient_desktop: 'size-full p-[20px]',
-                search_mobi: 'size-full py-[15px] pl-[10px] pr-[45px]',
+                search_mobi: 'size-full py-[16px] pl-[10px] pr-[20px]',
+                search_companies_mobi: 'size-full py-[15px]  pl-[20px]',
                 send_mobi: 'size-full px-[10px]',
                 contacts_page_desktop: 'h-[53px] w-[453px] px-4 py-3.5 2xl:w-[520px]',
                 contacts_page_info_desktop: '3xl:w-[452px] h-[53px] w-[484px] px-4 py-3.5 2xl:w-[520px]',
diff --git a/frontend-react/styles/globals.css b/frontend-react/styles/globals.css
index beb533030..469fb35a6 100644
--- a/frontend-react/styles/globals.css
+++ b/frontend-react/styles/globals.css
@@ -116,6 +116,18 @@
         background-origin: border-box;
         background-clip: padding-box, border-box;
     }
+
+
+::-webkit-scrollbar {
+    width: 2px; 
+}
+
+::-webkit-scrollbar-thumb {
+    background-color: rgba(135, 135, 151, 1); 
+   
+}
+
+
 }
 @layer base {
     * {


Reviews:
user: login: Margo-Bond
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-08T19:22:00Z
user: login: TaisNch
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-13T22:43:51Z
user: login: Margo-Bond
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-16T20:06:10Z

Review comments:
diff_hunk: @@ -28,7 +28,7 @@ export default function Companies() {
             ) : (
                 <>
                     <main className="bg-[#101030] text-white">
-                        <h1>Companies</h1>
+                        <CompaniesPageMobi />
                     </main>
path: frontend-react/app/companies/page.tsx
user: login: Margo-Bond
body: тег main перенести в компонент CompaniesPageMobi, заменить див с 47й строки на main. И дублируется фон
created_at: 2025-05-08T19:22:00Z
author_association: COLLABORATOR
diff_hunk: @@ -28,7 +28,7 @@ export default function Companies() {
             ) : (
                 <>
                     <main className="bg-[#101030] text-white">
-                        <h1>Companies</h1>
+                        <CompaniesPageMobi />
                     </main>
path: frontend-react/app/companies/page.tsx
user: login: TaisNch
body: исправлено
created_at: 2025-05-13T22:43:51Z
author_association: COLLABORATOR
diff_hunk: @@ -11,7 +11,7 @@ export default function Companies() {
     }, [])
 
     const isDesktop = useMediaQuery({
-        query: '(min-width: 768px)',
+        query: '(min-width: 769px)',
path: frontend-react/app/companies/page.tsx
user: login: Margo-Bond
body: 1240px
created_at: 2025-05-16T20:06:10Z
author_association: COLLABORATOR

PR comments:
user: login: Margo-Bond
created_at: 2025-05-08T19:05:12Z
body: 1. При ширине 768px мобильная страница не отображается
![image](https://github.com/user-attachments/assets/b67bc52f-684c-4b78-ac4b-3bff3cb4e635)
2. Убрать ховер и фокус  эффект на инпутах
![image](https://github.com/user-attachments/assets/1c30d783-ce7c-4f8e-8aeb-873e7dd5e1b8)
![image](https://github.com/user-attachments/assets/a269bf0c-e054-4828-bf0b-54cb4bf45827)
3. Изменить дизайн селектора в соответствии с макетом ниже
![image](https://github.com/user-attachments/assets/b3ed02a1-1b40-4652-8959-6fb71841e7de)
author_association: COLLABORATOR
user: login: TaisNch
created_at: 2025-05-13T22:45:38Z
body: сделано:
при ширине 768 страница отображается
![Снимок экрана 2025-05-14 004155](https://github.com/user-attachments/assets/f349c744-6e2d-4249-a02b-e794e0c034b1)
убран бордер фокуса инпутов
![Снимок экрана 2025-05-13 223036](https://github.com/user-attachments/assets/7117ddbf-99f5-41af-9a83-cd33be3a22e5)
![Снимок экрана 2025-05-13 223127](https://github.com/user-attachments/assets/8e9bd5f0-c9c0-4438-a525-2033a8da346e)
исправлен дизайн селектора
![Снимок экрана 2025-05-13 223134](https://github.com/user-attachments/assets/b77dec7f-87c2-4413-a50f-530fe6c1f0ed)

author_association: COLLABORATOR
user: login: Margo-Bond
created_at: 2025-05-15T22:04:22Z
body: 1. Открытый селектор не закрывается при клике вне его области - исправлено
2. Не должны отображаться пустые страницы, в пагинации должно отобрааться ровно столько страниц, сколько карточек. При поиск компаний epam карточек отображается на 2 страницы, далее страницы 3-6 пустые, они не должны отображаться - исправлено, а также исправлена ошибка поиска - фильтрация вставала на ту страницу, на которой начинался поиск (т.е. если стояли на 6 странице, то там и оставался), теперь поиск всегда возвращается на 1 страницу
![image](https://github.com/user-attachments/assets/a2fc6da6-b1f9-4a12-9ef6-2a55afaeeb74)

author_association: COLLABORATOR
user: login: Margo-Bond
created_at: 2025-05-16T20:23:43Z
body: В случае отсутствия нужной компании не должно отображаться символов "<" и ">", добавь текст "Ничего не найдено" по центру
![image](https://github.com/user-attachments/assets/5bd88d64-4769-48be-bcbb-74a4bd529a44)
как по аналогии со страницей Профессии. Только тут слишком большой отступ вертильный и много пустого пространства.
![image](https://github.com/user-attachments/assets/a86ad1e1-7c16-4578-be78-501372266e1c)

author_association: COLLABORATOR