Skip to content

Commit

Permalink
Merge pull request #58 from deriv-com/farabi/fix-landscape-view-issues
Browse files Browse the repository at this point in the history
Farabi/fix landscape view issues
  • Loading branch information
farabi-deriv authored Feb 25, 2025
2 parents 9748c1e + 6045cb4 commit 4d32cda
Show file tree
Hide file tree
Showing 14 changed files with 60 additions and 65 deletions.
6 changes: 3 additions & 3 deletions src/components/BottomSheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useRef, useCallback, useEffect } from "react";
import { useBottomSheetStore } from "@/stores/bottomSheetStore";
import { bottomSheetConfig } from "@/config/bottomSheetConfig";
import { useDeviceDetection } from "@/hooks/useDeviceDetection";
import { PrimaryButton } from "../ui/primary-button";
import { useOrientationStore } from "@/stores/orientationStore";

export const BottomSheet = () => {
const {
Expand All @@ -13,7 +13,7 @@ export const BottomSheet = () => {
actionButton,
setBottomSheet,
} = useBottomSheetStore();
const { isDesktop } = useDeviceDetection();
const { isLandscape } = useOrientationStore();

const sheetRef = useRef<HTMLDivElement>(null);
const dragStartY = useRef<number>(0);
Expand Down Expand Up @@ -162,7 +162,7 @@ export const BottomSheet = () => {
onTouchStart={handleTouchStart}
onMouseDown={handleMouseDown}
onClick={() => {
if (isDesktop) {
if (isLandscape) {
onDragDown?.();
setBottomSheet(false);
}
Expand Down
21 changes: 0 additions & 21 deletions src/components/BottomSheet/__tests__/BottomSheet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,27 +155,6 @@ describe("BottomSheet", () => {
expect(mockSetBottomSheet).toHaveBeenCalledWith(false);
});

it("closes bottom sheet when clicking handle bar on desktop", () => {
mockUseDeviceDetection.mockReturnValue({ isDesktop: true });
const mockOnDragDown = jest.fn();
mockUseBottomSheetStore.mockReturnValue({
showBottomSheet: true,
key: 'test-key',
height: '380px',
onDragDown: mockOnDragDown,
setBottomSheet: mockSetBottomSheet
});

const { container } = render(<BottomSheet />);

const handleBar = container.querySelector('[class*="flex flex-col items-center"]');
expect(handleBar).toBeInTheDocument();
fireEvent.click(handleBar!);

expect(mockOnDragDown).toHaveBeenCalled();
expect(mockSetBottomSheet).toHaveBeenCalledWith(false);
});

it("does not close bottom sheet when clicking handle bar on mobile", () => {
mockUseDeviceDetection.mockReturnValue({ isDesktop: false });
mockUseBottomSheetStore.mockReturnValue({
Expand Down
22 changes: 11 additions & 11 deletions src/components/Duration/DurationController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { BottomSheetHeader } from "@/components/ui/bottom-sheet-header";
import { DurationValueList } from "./components/DurationValueList";
import { HoursDurationValue } from "./components/HoursDurationValue";
import { useTradeStore } from "@/stores/tradeStore";
import { useDeviceDetection } from "@/hooks/useDeviceDetection";
import { PrimaryButton } from "@/components/ui/primary-button";
import { generateDurationValues as getDurationValues } from "@/utils/duration";
import { useBottomSheetStore } from "@/stores/bottomSheetStore";
import { useDebounce } from "@/hooks/useDebounce";
import { DesktopTradeFieldCard } from "@/components/ui/desktop-trade-field-card";
import type { DurationRangesResponse } from "@/services/api/rest/duration/types";
import { useOrientationStore } from "@/stores/orientationStore";

const DURATION_TYPES: Tab[] = [
{ label: "Ticks", value: "tick" },
Expand All @@ -30,7 +30,7 @@ export const DurationController: React.FC<DurationControllerProps> = ({
onClose,
}) => {
const { duration, setDuration } = useTradeStore();
const { isDesktop } = useDeviceDetection();
const { isLandscape } = useOrientationStore();
const { setBottomSheet } = useBottomSheetStore();
const isInitialRender = useRef(true);

Expand All @@ -52,7 +52,7 @@ export const DurationController: React.FC<DurationControllerProps> = ({
useDebounce(
localDuration,
(value) => {
if (isDesktop) {
if (isLandscape) {
setDuration(value);
}
},
Expand All @@ -74,14 +74,14 @@ export const DurationController: React.FC<DurationControllerProps> = ({
const newDuration = `${value} ${selectedType}`;
setLocalDuration(newDuration);
setDuration(newDuration); // Update store immediately on click
if (isDesktop) {
if (isLandscape) {
onClose?.();
}
};

const handleSave = () => {
setDuration(localDuration);
if (isDesktop) {
if (isLandscape) {
onClose?.();
} else {
setBottomSheet(false);
Expand All @@ -90,15 +90,15 @@ export const DurationController: React.FC<DurationControllerProps> = ({

const content = (
<>
<div className={isDesktop ? "flex" : ""}>
{!isDesktop && <BottomSheetHeader title="Duration" />}
<div className={isLandscape ? "flex" : ""}>
{!isLandscape && <BottomSheetHeader title="Duration" />}
<TabList
tabs={DURATION_TYPES}
selectedValue={selectedType}
onSelect={handleTypeSelect as (value: string) => void}
variant={isDesktop ? "vertical" : "chip"}
variant={isLandscape ? "vertical" : "chip"}
/>
<div className={`flex-1 relative bg-white ${isDesktop ? "px-2" : "px-8"}`}>
<div className={`flex-1 relative bg-white ${isLandscape ? "px-2" : "px-8"}`}>
{selectedType === "hour" ? (
<HoursDurationValue
selectedValue={selectedValue.toString()}
Expand All @@ -120,7 +120,7 @@ export const DurationController: React.FC<DurationControllerProps> = ({
)}
</div>
</div>
{!isDesktop && (
{!isLandscape && (
<div className="w-full p-3">
<PrimaryButton className="rounded-3xl" onClick={handleSave}>
Save
Expand All @@ -130,7 +130,7 @@ export const DurationController: React.FC<DurationControllerProps> = ({
</>
);

if (isDesktop) {
if (isLandscape) {
return (
<DesktopTradeFieldCard className="p-0">
<div className="w-[368px]">{content}</div>
Expand Down
10 changes: 5 additions & 5 deletions src/components/Duration/DurationField.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useState, useRef } from "react"
import { useTradeStore } from "@/stores/tradeStore"
import { useBottomSheetStore } from "@/stores/bottomSheetStore"
import { useDeviceDetection } from "@/hooks/useDeviceDetection"
import TradeParam from "@/components/TradeFields/TradeParam"
import { DurationController } from "./DurationController"
import { Popover } from "@/components/ui/popover"
import { DesktopTradeFieldCard } from "@/components/ui/desktop-trade-field-card"
import { useOrientationStore } from "@/stores/orientationStore"

interface DurationFieldProps {
className?: string
Expand All @@ -14,12 +14,12 @@ interface DurationFieldProps {
export const DurationField: React.FC<DurationFieldProps> = ({ className }) => {
const { duration } = useTradeStore()
const { setBottomSheet } = useBottomSheetStore()
const { isDesktop } = useDeviceDetection()
const { isLandscape } = useOrientationStore()
const [isOpen, setIsOpen] = useState(false)
const popoverRef = useRef<{ isClosing: boolean }>({ isClosing: false })

const handleClick = () => {
if (isDesktop) {
if (isLandscape) {
if (!popoverRef.current.isClosing) {
setIsOpen(!isOpen)
}
Expand All @@ -39,7 +39,7 @@ export const DurationField: React.FC<DurationFieldProps> = ({ className }) => {

return (
<div className="relative">
{isDesktop ? (
{isLandscape ? (
<DesktopTradeFieldCard isSelected={isOpen}>
<TradeParam
label="Duration"
Expand All @@ -56,7 +56,7 @@ export const DurationField: React.FC<DurationFieldProps> = ({ className }) => {
className={className}
/>
)}
{isDesktop && isOpen && (
{isLandscape && isOpen && (
<Popover
isOpen={isOpen}
onClose={handleClose}
Expand Down
2 changes: 1 addition & 1 deletion src/components/HowToTrade/HowToTrade.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const HowToTrade: React.FC = () => {
if (isDesktop) {
setIsModalOpen(true);
} else {
setBottomSheet(true, "how-to-trade", "90%", {
setBottomSheet(true, "how-to-trade", "80%", {
show: true,
label: "Got it",
onClick: () => setBottomSheet(false)
Expand Down
2 changes: 1 addition & 1 deletion src/components/HowToTrade/__tests__/HowToTrade.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('HowToTrade', () => {
const call = mockSetBottomSheet.mock.calls[0];
expect(call[0]).toBe(true);
expect(call[1]).toBe('how-to-trade');
expect(call[2]).toBe('90%');
expect(call[2]).toBe('80%');
expect(call[3]).toEqual(expect.objectContaining({
show: true,
label: "Got it",
Expand Down
4 changes: 2 additions & 2 deletions src/components/SideNav/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export const SideNav: React.FC<{ setMenuOpen: (open: boolean) => void; isMenuOpe
const location = useLocation();
const { isLoggedIn } = useClientStore();
const { isLandscape } = useOrientationStore();
const { isSidebarOpen, setSidebarOpen } = useMainLayoutStore();
const { isSidebarOpen, setSidebarOpen, isSideNavVisible } = useMainLayoutStore();

return (
<nav className={`${isLandscape ? 'flex' : 'hidden'} fixed z-[100] flex-col h-[100dvh] sticky top-0 w-16 border-r bg-white overflow-y-auto`}>
<nav className={`${isLandscape && isSideNavVisible ? 'flex' : 'hidden'} fixed z-[60] flex-col h-[100dvh] sticky top-0 w-16 border-r bg-white overflow-y-auto`}>
<div className="flex flex-col items-center gap-6 py-6">
{isLoggedIn && (
<>
Expand Down
21 changes: 10 additions & 11 deletions src/components/Stake/StakeController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ import React, { useEffect, useState } from "react";
import { useTradeStore } from "@/stores/tradeStore";
import { useClientStore } from "@/stores/clientStore";
import { BottomSheetHeader } from "@/components/ui/bottom-sheet-header";
import { useDeviceDetection } from "@/hooks/useDeviceDetection";
import { useBottomSheetStore } from "@/stores/bottomSheetStore";
import { useDebounce } from "@/hooks/useDebounce";
import { StakeInputLayout } from "./components/StakeInputLayout";
import { PrimaryButton } from "@/components/ui/primary-button";
import { parseStakeAmount, STAKE_CONFIG } from "@/config/stake";
import { DesktopTradeFieldCard } from "@/components/ui/desktop-trade-field-card";
import { validateStake } from "./utils/validation";
import { parseDuration, formatDuration } from "@/utils/duration";
import { createSSEConnection } from "@/services/api/sse/createSSEConnection";
import { tradeTypeConfigs } from "@/config/tradeTypes";
import { useOrientationStore } from "@/stores/orientationStore";

interface ButtonState {
loading: boolean;
Expand All @@ -28,7 +27,7 @@ interface StakeControllerProps {}
export const StakeController: React.FC<StakeControllerProps> = () => {
const { stake, setStake, trade_type, duration, payouts, setPayouts } = useTradeStore();
const { currency, token } = useClientStore();
const { isDesktop } = useDeviceDetection();
const { isLandscape } = useOrientationStore();
const { setBottomSheet } = useBottomSheetStore();

const [localStake, setLocalStake] = React.useState(stake);
Expand Down Expand Up @@ -184,7 +183,7 @@ export const StakeController: React.FC<StakeControllerProps> = () => {
const handleStakeChange = (value: string) => {
if (preventExceedingMax(value)) return;

if (isDesktop) {
if (isLandscape) {
setLocalStake(value);
validateStakeOnly(value);
return;
Expand All @@ -195,18 +194,18 @@ export const StakeController: React.FC<StakeControllerProps> = () => {
};

useEffect(() => {
if (!isDesktop) return;
if (!isLandscape) return;

if (debouncedStake !== stake) {
const validation = validateStakeOnly(debouncedStake);
if (!validation.error) {
setStake(debouncedStake);
}
}
}, [isDesktop, debouncedStake, stake]);
}, [isLandscape, debouncedStake, stake]);

const handleSave = () => {
if (isDesktop) return;
if (isLandscape) return;

const validation = validateAndUpdateStake(localStake);
if (validation.error) return;
Expand All @@ -217,7 +216,7 @@ export const StakeController: React.FC<StakeControllerProps> = () => {

const content = (
<>
{!isDesktop && <BottomSheetHeader title="Stake" />}
{!isLandscape && <BottomSheetHeader title="Stake" />}
<div className="flex flex-col justify-between flex-grow px-6">
<StakeInputLayout
value={localStake}
Expand All @@ -226,15 +225,15 @@ export const StakeController: React.FC<StakeControllerProps> = () => {
errorMessage={errorMessage}
maxPayout={payouts.max}
payoutValues={payouts.values}
isDesktop={isDesktop}
isDesktop={isLandscape}
loading={Object.values(buttonStates).some(state => state.loading)}
loadingStates={Object.keys(buttonStates).reduce((acc, key) => ({
...acc,
[key]: buttonStates[key].loading
}), {})}
/>
</div>
{!isDesktop && (
{!isLandscape && (
<div className="w-full py-6 px-3">
<PrimaryButton
className="rounded-3xl"
Expand All @@ -248,7 +247,7 @@ export const StakeController: React.FC<StakeControllerProps> = () => {
</>
);

if (isDesktop) {
if (isLandscape) {
return (
<div className="w-[480px]">{content}</div>
);
Expand Down
6 changes: 3 additions & 3 deletions src/components/Stake/StakeField.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react"
import { useDeviceDetection } from "@/hooks/useDeviceDetection"
import TradeParam from "@/components/TradeFields/TradeParam"
import { Tooltip } from "@/components/ui/tooltip"
import { useStakeField } from "./hooks/useStakeField"
import { cn } from "@/lib/utils"
import { useOrientationStore } from "@/stores/orientationStore"

interface StakeFieldProps {
className?: string
Expand All @@ -16,7 +16,7 @@ export const StakeField: React.FC<StakeFieldProps> = ({
onSelect,
onError,
}) => {
const { isDesktop } = useDeviceDetection()
const { isLandscape } = useOrientationStore()
const {
stake,
currency,
Expand All @@ -32,7 +32,7 @@ export const StakeField: React.FC<StakeFieldProps> = ({
handleMobileClick,
} = useStakeField({ onSelect, onError })

if (!isDesktop) {
if (!isLandscape) {
return (
<div className="flex flex-col">
<div
Expand Down
8 changes: 4 additions & 4 deletions src/components/TradeFields/TradeParamField.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useRef } from "react";
import { useDeviceDetection } from "@/hooks/useDeviceDetection";
import TradeParam from "./TradeParam";
import { useOrientationStore } from "@/stores/orientationStore";

interface TradeParamFieldProps {
label: string;
Expand All @@ -17,12 +17,12 @@ export const TradeParamField: React.FC<TradeParamFieldProps> = ({
onSelect,
className,
}) => {
const { isDesktop } = useDeviceDetection();
const { isLandscape } = useOrientationStore();
const [showPopover, setShowPopover] = useState(false);
const paramRef = useRef<HTMLDivElement>(null);

const handleClick = () => {
if (isDesktop) {
if (isLandscape) {
setShowPopover(true);
} else {
onSelect?.();
Expand Down Expand Up @@ -62,7 +62,7 @@ export const TradeParamField: React.FC<TradeParamFieldProps> = ({
className={className}
/>

{isDesktop && showPopover && (
{isLandscape && showPopover && (
<>
{/* Popover */}
<div
Expand Down
2 changes: 1 addition & 1 deletion src/screens/ContractDetailsPage/ContractDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const MobileContractDetailsPage: React.FC = () => {
<div className="flex-1 overflow-y-auto w-full lg:w-3/5 mx-auto">
<div className="p-2 pb-[72px]">
<ContractSummary />
<div className="min-h-[400px] bg-white rounded-lg border-b border-gray-300">
<div className="min-h-[400px] mt-4 bg-white rounded-lg border-b border-gray-300">
<ContractDetailsChart />
</div>
<OrderDetails />
Expand Down
Loading

0 comments on commit 4d32cda

Please sign in to comment.