{"id":31,"date":"2026-03-10T17:14:51","date_gmt":"2026-03-10T14:14:51","guid":{"rendered":"https:\/\/bonsai.panshiny.ru\/?page_id=31"},"modified":"2026-03-10T17:15:57","modified_gmt":"2026-03-10T14:15:57","slug":"%d0%bf%d0%b0%d0%b2%d0%b5%d0%bb","status":"publish","type":"page","link":"https:\/\/bonsai.panshiny.ru\/?page_id=31","title":{"rendered":"\u041f\u0430\u0432\u0435\u043b"},"content":{"rendered":"\nimport React, { useState, useRef, useEffect } from &#8216;react&#8217;;\nimport { Info, ChevronRight, ChevronDown } from &#8216;lucide-react&#8217;;\n\n\/\/ \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0430\u043a\u0435\u0442\u0443\nconst CATEGORIES = [\n  { id: &#8216;mb-repair&#8217;, name: &#8216;\u0420\u0435\u043c\u043e\u043d\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u044b&#8217; },\n  { id: &#8216;all&#8217;, name: &#8216;\u0412\u0441\u0435&#8217; },\n  { id: &#8216;warranty&#8217;, name: &#8216;\u0413\u0430\u0440\u0430\u043d\u0442\u0438\u0439\u043d\u044b\u0439 \u0440\u0435\u043c\u043e\u043d\u0442&#8217; },\n  { id: &#8216;diagnostics&#8217;, name: &#8216;\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u0430\u043a\u0442\u0438\u043a\u0430&#8217; },\n  { id: &#8216;software&#8217;, name: &#8216;\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0439 \u0440\u0435\u043c\u043e\u043d\u0442&#8217; },\n  { id: &#8216;hardware&#8217;, name: &#8216;\u0420\u0435\u043c\u043e\u043d\u0442 \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438&#8217; },\n];\n\nconst SERVICES_DATA = {\n  &#8216;mb-repair&#8217;: [\n    { id: &#8216;s1&#8217;, name: &#8216;\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u0438 \u043a\u043e\u043d\u0441\u0443\u043b\u044c\u0442\u0430\u0446\u0438\u044f&#8217;, price: &#8216;\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e&#8217;, isFree: true },\n    { id: &#8216;s2&#8217;, name: &#8216;\u0412\u044b\u0435\u0437\u0434 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u0430 \u043d\u0430 \u0434\u043e\u043c&#8217;, price: &#8216;\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e&#8217;, isFree: true },\n    { id: &#8216;s3&#8217;, name: &#8216;\u0420\u0435\u043c\u043e\u043d\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u044b&#8217;, price: &#8216;\u043e\u0442 1 990 \u20bd&#8217;, isFree: false },\n    { id: &#8216;s4&#8217;, name: &#8216;\u0417\u0430\u043c\u0435\u043d\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u044b&#8217;, price: &#8216;\u043e\u0442 2 490 \u20bd&#8217;, isFree: false },\n    { id: &#8216;s5&#8217;, name: &#8216;\u0417\u0430\u043c\u0435\u043d\u0430 \u0447\u0438\u043f\u043e\u0432 \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u044b&#8217;, price: &#8216;\u043e\u0442 290 \u20bd&#8217;, isFree: false },\n  ],\n  &#8216;all&#8217;: [\n    { id: &#8216;s6&#8217;, name: &#8216;\u041a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u0430\u044f \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430&#8217;, price: &#8216;\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e&#8217;, isFree: true },\n    { id: &#8216;s7&#8217;, name: &#8216;\u041b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0440\u0435\u043c\u043e\u043d\u0442&#8217;, price: &#8216;\u043e\u0442 500 \u20bd&#8217;, isFree: false },\n  ],\n  &#8216;warranty&#8217;: [\n    { id: &#8216;s8&#8217;, name: &#8216;\u0413\u0430\u0440\u0430\u043d\u0442\u0438\u0439\u043d\u043e\u0435 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435&#8217;, price: &#8216;\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e&#8217;, isFree: true },\n  ],\n  &#8216;diagnostics&#8217;: [\n    { id: &#8216;s9&#8217;, name: &#8216;\u0410\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u0430\u044f \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430&#8217;, price: &#8216;\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e&#8217;, isFree: true },\n    { id: &#8216;s10&#8217;, name: &#8216;\u0427\u0438\u0441\u0442\u043a\u0430 \u043e\u0442 \u043f\u044b\u043b\u0438 \u0438 \u0437\u0430\u043c\u0435\u043d\u0430 \u0442\u0435\u0440\u043c\u043e\u043f\u0430\u0441\u0442\u044b&#8217;, price: &#8216;\u043e\u0442 990 \u20bd&#8217;, isFree: false },\n  ],\n  &#8216;software&#8217;: [\n    { id: &#8216;s11&#8217;, name: &#8216;\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b&#8217;, price: &#8216;\u043e\u0442 1 490 \u20bd&#8217;, isFree: false },\n    { id: &#8216;s12&#8217;, name: &#8216;\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0432\u0438\u0440\u0443\u0441\u043e\u0432&#8217;, price: &#8216;\u043e\u0442 790 \u20bd&#8217;, isFree: false },\n  ],\n  &#8216;hardware&#8217;: [\n    { id: &#8216;s13&#8217;, name: &#8216;\u0417\u0430\u043c\u0435\u043d\u0430 \u0436\u0435\u0441\u0442\u043a\u043e\u0433\u043e \u0434\u0438\u0441\u043a\u0430&#8217;, price: &#8216;\u043e\u0442 890 \u20bd&#8217;, isFree: false },\n    { id: &#8216;s14&#8217;, name: &#8216;\u0423\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438&#8217;, price: &#8216;\u043e\u0442 590 \u20bd&#8217;, isFree: false },\n  ],\n};\n\nexport default function App() {\n  const [activeCategoryId, setActiveCategoryId] = useState(&#8216;mb-repair&#8217;);\n  const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n  const dropdownRef = useRef(null);\n\n  \/\/ \u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0434\u0440\u043e\u043f\u0434\u0430\u0443\u043d\u0430 \u043f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u0432\u043d\u0435 \u0435\u0433\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (\u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438)\n  useEffect(() => {\n    function handleClickOutside(event) {\n      if (dropdownRef.current &#038;&#038; !dropdownRef.current.contains(event.target)) {\n        setIsDropdownOpen(false);\n      }\n    }\n    document.addEventListener(&#8216;mousedown&#8217;, handleClickOutside);\n    return () => document.removeEventListener(&#8216;mousedown&#8217;, handleClickOutside);\n  }, []);\n\n  const activeCategory = CATEGORIES.find(c => c.id === activeCategoryId);\n  const currentServices = SERVICES_DATA[activeCategoryId] || [];\n\n  return (\n    <div className=\"min-h-screen bg-[#F4F6FB] py-12 px-4 sm:px-6 lg:px-8 font-sans text-[#1A1A1A]\">\n      <div className=\"max-w-[1080px] mx-auto\">\n        \n        {\/* \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a *\/}\n        <h1 className=\"text-3xl md:text-[40px] font-bold mb-8 md:mb-12 tracking-tight\">\n          \u0426\u0435\u043d\u044b \u043d\u0430 \u0440\u0435\u043c\u043e\u043d\u0442 <span className=\"text-[#1B5BFF]\">\u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u044b<\/span>\n        <\/h1>\n\n        {\/* \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441\u0435\u0442\u043a\u0438 *\/}\n        <div className=\"flex flex-col lg:flex-row gap-6\">\n          \n          {\/* \u041b\u0435\u0432\u0430\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0430: \u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 (Desktop) *\/}\n          <div className=\"hidden lg:block w-[320px] shrink-0\">\n            <div className=\"bg-white rounded-[24px] p-6 shadow-[0_2px_20px_rgba(0,0,0,0.02)]\">\n              <h2 className=\"text-xl font-bold mb-4 px-2\">\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438<\/h2>\n              <ul className=\"space-y-1\">\n                {CATEGORIES.map((category) => {\n                  const isActive = activeCategoryId === category.id;\n                  return (\n                    <li key={category.id}>\n                      <button\n                        onClick={() => setActiveCategoryId(category.id)}\n                        className={`w-full text-left relative px-4 py-3.5 rounded-xl transition-all duration-200 ${\n                          isActive \n                            ? &#8216;bg-[#F0F5FF] text-[#1B5BFF] font-semibold&#8217; \n                            : &#8216;text-[#5A637A] hover:bg-[#F8FAFC] hover:text-[#1A1A1A]&#8217;\n                        }`}\n                      >\n                        {\/* \u0421\u0438\u043d\u0438\u0439 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430 *\/}\n                        {isActive &#038;&#038; (\n                          <div className=\"absolute left-0 top-1\/2 -translate-y-1\/2 w-[4px] h-[24px] bg-[#1B5BFF] rounded-r-md\" \/>\n                        )}\n                        <span className=\"text-[15px]\">{category.name}<\/span>\n                      <\/button>\n                    <\/li>\n                  );\n                })}\n              <\/ul>\n            <\/div>\n          <\/div>\n\n          {\/* \u041f\u0440\u0430\u0432\u0430\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0430: \u0423\u0441\u043b\u0443\u0433\u0438 \u0438 \u0426\u0435\u043d\u044b *\/}\n          <div className=\"flex-1\">\n            <div className=\"bg-white rounded-[24px] p-5 sm:p-8 shadow-[0_2px_20px_rgba(0,0,0,0.02)]\">\n              \n              {\/* \u0428\u0430\u043f\u043a\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b *\/}\n              <div className=\"flex flex-wrap items-center justify-between border-b border-[#EAEEF5] pb-5 mb-2 gap-4\">\n                <div className=\"flex items-center gap-3\">\n                  <span className=\"text-lg font-bold\">\u0423\u0441\u043b\u0443\u0433\u0430<\/span>\n                  \n                  {\/* \u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 (Mobile &#038; Tablet) *\/}\n                  <div className=\"lg:hidden relative\" ref={dropdownRef}>\n                    <button\n                      onClick={() => setIsDropdownOpen(!isDropdownOpen)}\n                      className=&#187;flex items-center gap-2 bg-[#F4F6FB] hover:bg-[#EDF1F7] transition-colors rounded-[12px] px-4 py-2 text-[14px] font-medium text-[#1A1A1A]&#187;\n                    >\n                      <span className=\"max-w-[180px] sm:max-w-xs truncate\">{activeCategory?.name}<\/span>\n                      <ChevronDown size={16} className={`text-[#8C98AE] transition-transform duration-200 ${isDropdownOpen ? 'rotate-180' : ''}`} \/>\n                    <\/button>\n\n                    {\/* \u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a *\/}\n                    {isDropdownOpen &#038;&#038; (\n                      <div className=\"absolute top-full left-0 mt-2 w-max min-w-[240px] bg-white rounded-xl shadow-[0_10px_40px_rgba(0,0,0,0.08)] border border-[#EAEEF5] py-2 z-20\">\n                        {CATEGORIES.map((category) => (\n                          <button\n                            key={category.id}\n                            onClick={() => {\n                              setActiveCategoryId(category.id);\n                              setIsDropdownOpen(false);\n                            }}\n                            className={`w-full text-left px-4 py-2.5 text-sm transition-colors ${\n                              activeCategoryId === category.id \n                                ? &#8216;bg-[#F0F5FF] text-[#1B5BFF] font-medium&#8217; \n                                : &#8216;text-[#5A637A] hover:bg-[#F8FAFC]&#8217;\n                            }`}\n                          >\n                            {category.name}\n                          <\/button>\n                        ))}\n                      <\/div>\n                    )}\n                  <\/div>\n                <\/div>\n                <span className=\"text-lg font-bold w-[100px] sm:w-[130px] lg:w-[150px]\">\u0426\u0435\u043d\u0430<\/span>\n              <\/div>\n\n              {\/* \u0421\u043f\u0438\u0441\u043e\u043a \u0443\u0441\u043b\u0443\u0433 *\/}\n              <div className=\"flex flex-col\">\n                {currentServices.map((service) => (\n                  <div \n                    key={service.id} \n                    className=\"flex items-center justify-between py-4 border-b border-[#F4F6FB] hover:bg-[#F8FAFC] transition-colors rounded-xl px-2 sm:px-4 -mx-2 sm:-mx-4 cursor-pointer group\"\n                  >\n                    <span className=\"text-[14px] sm:text-[15px] font-medium text-[#1A1A1A] pr-4 flex-1\">\n                      {service.name}\n                    <\/span>\n                    <div className=\"flex items-center justify-between w-[100px] sm:w-[130px] lg:w-[150px] shrink-0\">\n                      <span className={`text-[14px] sm:text-[15px] font-semibold whitespace-nowrap ${service.isFree ? 'text-[#1A1A1A]' : 'text-[#1A1A1A]'}`}>\n                        {service.price}\n                      <\/span>\n                      {service.isFree ? (\n                        <Info size={18} strokeWidth={1.5} className=\"text-[#A0ABC0] ml-2\" \/>\n                      ) : (\n                        <ChevronRight size={18} strokeWidth={2} className=\"text-[#A0ABC0] ml-2 opacity-50 group-hover:opacity-100 transition-opacity\" \/>\n                      )}\n                    <\/div>\n                  <\/div>\n                ))}\n              <\/div>\n\n              {\/* \u0424\u0443\u0442\u0435\u0440-\u0434\u0438\u0441\u043a\u043b\u0435\u0439\u043c\u0435\u0440 *\/}\n              <div className=\"mt-8 pt-6 border-t border-[#F4F6FB]\">\n                <p className=\"text-[13px] text-[#8C98AE] leading-relaxed\">\n                  \u0421\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u0431\u0435\u0437 \u0443\u0447\u0451\u0442\u0430 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0442\u0443\u044e\u0449\u0438\u0445 \u0438 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043c\u043e\u0434\u0435\u043b\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\n                <\/p>\n              <\/div>\n\n            <\/div>\n          <\/div>\n\n        <\/div>\n      <\/div>\n    <\/div>\n  );\n}\n","protected":false},"excerpt":{"rendered":"<p>import React, { useState, useRef, useEffect } from &#8216;react&#8217;; import { Info, ChevronRight, ChevronDown } from &#8216;lucide-react&#8217;; \/\/ \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0430\u043a\u0435\u0442\u0443 const CATEGORIES = [ { id: &#8216;mb-repair&#8217;, name: &#8216;\u0420\u0435\u043c\u043e\u043d\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u044b&#8217; }, { id: &#8216;all&#8217;, name: &#8216;\u0412\u0441\u0435&#8217; }, { id: &#8216;warranty&#8217;, name: &#8216;\u0413\u0430\u0440\u0430\u043d\u0442\u0438\u0439\u043d\u044b\u0439 \u0440\u0435\u043c\u043e\u043d\u0442&#8217; }, { id: &#8216;diagnostics&#8217;, name: &#8216;\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u0430\u043a\u0442\u0438\u043a\u0430&#8217; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-31","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=\/wp\/v2\/pages\/31","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=31"}],"version-history":[{"count":2,"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=\/wp\/v2\/pages\/31\/revisions"}],"predecessor-version":[{"id":34,"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=\/wp\/v2\/pages\/31\/revisions\/34"}],"wp:attachment":[{"href":"https:\/\/bonsai.panshiny.ru\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=31"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}