Create mobile calender service
This commit is contained in:
559
mobile-calendar/src/App.sass
Normal file
559
mobile-calendar/src/App.sass
Normal file
@@ -0,0 +1,559 @@
|
||||
// Mobile Calendar App Styles
|
||||
// Clean, beautiful design for calendar events
|
||||
|
||||
:root
|
||||
--primary-color: #007AFF
|
||||
--secondary-color: #5856D6
|
||||
--success-color: #34C759
|
||||
--danger-color: #FF3B30
|
||||
--warning-color: #FF9500
|
||||
--background-color: #f8f9fa
|
||||
--surface-color: #ffffff
|
||||
--border-color: #e1e5e9
|
||||
--text-primary: #1d1d1f
|
||||
--text-secondary: #6e6e73
|
||||
--text-muted: #8e8e93
|
||||
--shadow-light: 0 2px 8px rgba(0, 0, 0, 0.1)
|
||||
--shadow-medium: 0 4px 16px rgba(0, 0, 0, 0.15)
|
||||
--border-radius: 12px
|
||||
--border-radius-small: 8px
|
||||
--spacing-xs: 4px
|
||||
--spacing-sm: 8px
|
||||
--spacing-md: 16px
|
||||
--spacing-lg: 24px
|
||||
--spacing-xl: 32px
|
||||
|
||||
*
|
||||
margin: 0
|
||||
padding: 0
|
||||
box-sizing: border-box
|
||||
|
||||
body
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif
|
||||
background-color: var(--background-color)
|
||||
color: var(--text-primary)
|
||||
line-height: 1.5
|
||||
-webkit-font-smoothing: antialiased
|
||||
-moz-osx-font-smoothing: grayscale
|
||||
|
||||
.app
|
||||
min-height: 100vh
|
||||
display: flex
|
||||
flex-direction: column
|
||||
max-width: 100vw
|
||||
overflow-x: hidden
|
||||
|
||||
&.calendar-app
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)
|
||||
|
||||
.main
|
||||
background: transparent
|
||||
|
||||
// Header
|
||||
.header
|
||||
background: var(--surface-color)
|
||||
border-bottom: 1px solid var(--border-color)
|
||||
padding: var(--spacing-sm) var(--spacing-md)
|
||||
position: sticky
|
||||
top: 0
|
||||
z-index: 100
|
||||
box-shadow: var(--shadow-light)
|
||||
|
||||
.header-content
|
||||
display: flex
|
||||
flex-direction: column
|
||||
gap: var(--spacing-md)
|
||||
max-width: 600px
|
||||
margin: 0 auto
|
||||
|
||||
h1
|
||||
font-size: 1.5rem
|
||||
font-weight: 600
|
||||
color: var(--text-primary)
|
||||
display: flex
|
||||
align-items: center
|
||||
gap: var(--spacing-sm)
|
||||
justify-content: center
|
||||
|
||||
svg
|
||||
color: var(--primary-color)
|
||||
font-size: 1.25rem
|
||||
|
||||
.month-navigation
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
gap: var(--spacing-md)
|
||||
|
||||
.current-month
|
||||
font-size: 1.125rem
|
||||
font-weight: 600
|
||||
color: var(--text-primary)
|
||||
margin: 0
|
||||
min-width: 140px
|
||||
text-align: center
|
||||
|
||||
.btn-icon
|
||||
width: 40px
|
||||
height: 40px
|
||||
border-radius: 50%
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
background: var(--background-color)
|
||||
border: 1px solid var(--border-color)
|
||||
|
||||
&:hover
|
||||
background: var(--primary-color)
|
||||
color: white
|
||||
border-color: var(--primary-color)
|
||||
|
||||
.view-controls
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: space-between
|
||||
gap: var(--spacing-md)
|
||||
padding-top: var(--spacing-sm)
|
||||
border-top: 1px solid var(--border-color)
|
||||
|
||||
.view-type-toggle
|
||||
display: flex
|
||||
gap: var(--spacing-xs)
|
||||
background: var(--background-color)
|
||||
padding: 4px
|
||||
border-radius: var(--border-radius-small)
|
||||
|
||||
.btn
|
||||
padding: var(--spacing-xs) var(--spacing-md)
|
||||
border-radius: var(--border-radius-small)
|
||||
font-size: 0.875rem
|
||||
|
||||
.user-select
|
||||
padding: var(--spacing-sm)
|
||||
border: 1px solid var(--border-color)
|
||||
border-radius: var(--border-radius-small)
|
||||
background: var(--surface-color)
|
||||
font-size: 0.875rem
|
||||
min-width: 120px
|
||||
|
||||
&:focus
|
||||
outline: none
|
||||
border-color: var(--primary-color)
|
||||
box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1)
|
||||
|
||||
// Main Content
|
||||
.main
|
||||
flex: 1
|
||||
padding: var(--spacing-md)
|
||||
max-width: 600px
|
||||
margin: 0 auto
|
||||
width: 100%
|
||||
padding-bottom: 100px // Space for FAB
|
||||
|
||||
// Error Message
|
||||
.error-message
|
||||
background: var(--danger-color)
|
||||
color: white
|
||||
padding: var(--spacing-md)
|
||||
border-radius: var(--border-radius-small)
|
||||
margin-bottom: var(--spacing-md)
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: space-between
|
||||
font-weight: 500
|
||||
|
||||
button
|
||||
background: none
|
||||
border: none
|
||||
color: white
|
||||
font-size: 1.25rem
|
||||
cursor: pointer
|
||||
padding: 0
|
||||
width: 24px
|
||||
height: 24px
|
||||
border-radius: 50%
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
|
||||
&:hover
|
||||
background: rgba(255, 255, 255, 0.1)
|
||||
|
||||
// Loading State
|
||||
.loading
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
justify-content: center
|
||||
height: 60vh
|
||||
color: var(--text-secondary)
|
||||
|
||||
.loading-icon
|
||||
font-size: 3rem
|
||||
color: var(--primary-color)
|
||||
margin-bottom: var(--spacing-md)
|
||||
animation: pulse 2s infinite
|
||||
|
||||
p
|
||||
font-size: 1.1rem
|
||||
font-weight: 500
|
||||
|
||||
@keyframes pulse
|
||||
0%, 100%
|
||||
opacity: 1
|
||||
50%
|
||||
opacity: 0.5
|
||||
|
||||
// Calendar Content
|
||||
.calendar-content
|
||||
display: flex
|
||||
flex-direction: column
|
||||
gap: var(--spacing-lg)
|
||||
|
||||
// Empty State
|
||||
.empty-state
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
justify-content: center
|
||||
padding: var(--spacing-xl)
|
||||
background: var(--surface-color)
|
||||
border-radius: var(--border-radius)
|
||||
box-shadow: var(--shadow-light)
|
||||
text-align: center
|
||||
|
||||
svg
|
||||
font-size: 3rem
|
||||
margin-bottom: var(--spacing-md)
|
||||
color: var(--primary-color)
|
||||
opacity: 0.5
|
||||
|
||||
p
|
||||
font-size: 1.1rem
|
||||
font-weight: 600
|
||||
color: var(--text-primary)
|
||||
margin-bottom: var(--spacing-sm)
|
||||
|
||||
small
|
||||
color: var(--text-secondary)
|
||||
line-height: 1.4
|
||||
|
||||
// Events List
|
||||
.events-list
|
||||
display: flex
|
||||
flex-direction: column
|
||||
gap: var(--spacing-lg)
|
||||
|
||||
.day-section
|
||||
background: var(--surface-color)
|
||||
border-radius: var(--border-radius)
|
||||
box-shadow: var(--shadow-light)
|
||||
overflow: hidden
|
||||
|
||||
.day-header
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%)
|
||||
color: white
|
||||
padding: var(--spacing-md)
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: space-between
|
||||
|
||||
h3
|
||||
font-size: 1.125rem
|
||||
font-weight: 600
|
||||
margin: 0
|
||||
|
||||
.event-count
|
||||
background: rgba(255, 255, 255, 0.2)
|
||||
padding: 4px 8px
|
||||
border-radius: 12px
|
||||
font-size: 0.75rem
|
||||
font-weight: 500
|
||||
|
||||
.day-events
|
||||
padding: var(--spacing-sm)
|
||||
display: flex
|
||||
flex-direction: column
|
||||
gap: var(--spacing-sm)
|
||||
|
||||
// Calendar Event
|
||||
.calendar-event
|
||||
background: var(--surface-color)
|
||||
border: 1px solid var(--border-color)
|
||||
border-left: 4px solid var(--primary-color)
|
||||
border-radius: var(--border-radius-small)
|
||||
padding: var(--spacing-md)
|
||||
display: flex
|
||||
align-items: flex-start
|
||||
justify-content: space-between
|
||||
gap: var(--spacing-md)
|
||||
transition: all 0.2s ease
|
||||
|
||||
&:hover
|
||||
box-shadow: var(--shadow-medium)
|
||||
transform: translateY(-1px)
|
||||
|
||||
.event-content
|
||||
flex: 1
|
||||
min-width: 0
|
||||
|
||||
.event-text
|
||||
font-weight: 500
|
||||
color: var(--text-primary)
|
||||
font-size: 1rem
|
||||
margin-bottom: var(--spacing-xs)
|
||||
word-break: break-word
|
||||
|
||||
.event-user
|
||||
font-size: 0.875rem
|
||||
font-weight: 600
|
||||
opacity: 0.8
|
||||
|
||||
.event-actions
|
||||
display: flex
|
||||
gap: var(--spacing-xs)
|
||||
flex-shrink: 0
|
||||
|
||||
.edit-form
|
||||
width: 100%
|
||||
display: flex
|
||||
flex-direction: column
|
||||
gap: var(--spacing-sm)
|
||||
|
||||
.form-group
|
||||
display: flex
|
||||
flex-direction: column
|
||||
|
||||
label
|
||||
font-size: 0.875rem
|
||||
font-weight: 500
|
||||
color: var(--text-secondary)
|
||||
margin-bottom: var(--spacing-xs)
|
||||
|
||||
input, select
|
||||
width: 100%
|
||||
padding: var(--spacing-sm)
|
||||
border: 1px solid var(--border-color)
|
||||
border-radius: var(--border-radius-small)
|
||||
font-size: 0.875rem
|
||||
background: var(--surface-color)
|
||||
|
||||
&:focus
|
||||
outline: none
|
||||
border-color: var(--primary-color)
|
||||
box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1)
|
||||
|
||||
.edit-actions
|
||||
display: flex
|
||||
gap: var(--spacing-sm)
|
||||
justify-content: flex-end
|
||||
margin-top: var(--spacing-sm)
|
||||
|
||||
// Buttons
|
||||
.btn
|
||||
border: none
|
||||
border-radius: var(--border-radius-small)
|
||||
padding: var(--spacing-sm) var(--spacing-md)
|
||||
font-size: 0.875rem
|
||||
font-weight: 500
|
||||
cursor: pointer
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
gap: var(--spacing-xs)
|
||||
transition: all 0.2s ease
|
||||
text-decoration: none
|
||||
|
||||
&:disabled
|
||||
opacity: 0.5
|
||||
cursor: not-allowed
|
||||
|
||||
&.btn-primary
|
||||
background: var(--primary-color)
|
||||
color: white
|
||||
|
||||
&:hover:not(:disabled)
|
||||
background: #0056b3
|
||||
transform: translateY(-1px)
|
||||
|
||||
&.btn-secondary
|
||||
background: var(--border-color)
|
||||
color: var(--text-primary)
|
||||
|
||||
&:hover:not(:disabled)
|
||||
background: #d1d5db
|
||||
|
||||
&.btn-danger
|
||||
background: var(--danger-color)
|
||||
color: white
|
||||
|
||||
&:hover:not(:disabled)
|
||||
background: #dc3545
|
||||
|
||||
&.btn-small
|
||||
padding: var(--spacing-xs)
|
||||
font-size: 0.75rem
|
||||
width: 32px
|
||||
height: 32px
|
||||
|
||||
svg
|
||||
font-size: 0.875rem
|
||||
|
||||
svg
|
||||
font-size: 1rem
|
||||
|
||||
// Add Form Overlay
|
||||
.add-form-overlay
|
||||
position: fixed
|
||||
top: 0
|
||||
left: 0
|
||||
right: 0
|
||||
bottom: 0
|
||||
background: rgba(0, 0, 0, 0.5)
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
z-index: 1000
|
||||
padding: var(--spacing-md)
|
||||
|
||||
.add-form
|
||||
background: var(--surface-color)
|
||||
border-radius: var(--border-radius)
|
||||
padding: var(--spacing-lg)
|
||||
width: 100%
|
||||
max-width: 400px
|
||||
box-shadow: var(--shadow-medium)
|
||||
max-height: 80vh
|
||||
overflow-y: auto
|
||||
|
||||
h3
|
||||
font-size: 1.25rem
|
||||
font-weight: 600
|
||||
margin-bottom: var(--spacing-md)
|
||||
color: var(--text-primary)
|
||||
text-align: center
|
||||
|
||||
.form-group
|
||||
display: flex
|
||||
flex-direction: column
|
||||
margin-bottom: var(--spacing-md)
|
||||
|
||||
label
|
||||
font-size: 0.875rem
|
||||
font-weight: 500
|
||||
color: var(--text-secondary)
|
||||
margin-bottom: var(--spacing-xs)
|
||||
|
||||
input, select
|
||||
width: 100%
|
||||
padding: var(--spacing-md)
|
||||
border: 1px solid var(--border-color)
|
||||
border-radius: var(--border-radius-small)
|
||||
font-size: 1rem
|
||||
background: var(--surface-color)
|
||||
|
||||
&:focus
|
||||
outline: none
|
||||
border-color: var(--primary-color)
|
||||
box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1)
|
||||
|
||||
.form-actions
|
||||
display: flex
|
||||
gap: var(--spacing-sm)
|
||||
justify-content: flex-end
|
||||
margin-top: var(--spacing-lg)
|
||||
|
||||
// Floating Action Button
|
||||
.fab-container
|
||||
position: fixed
|
||||
bottom: var(--spacing-lg)
|
||||
right: var(--spacing-lg)
|
||||
z-index: 100
|
||||
|
||||
.fab
|
||||
width: 56px
|
||||
height: 56px
|
||||
border-radius: 50%
|
||||
background: var(--primary-color)
|
||||
color: white
|
||||
border: none
|
||||
cursor: pointer
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
font-size: 1.25rem
|
||||
box-shadow: var(--shadow-medium)
|
||||
transition: all 0.2s ease
|
||||
|
||||
&:hover
|
||||
background: #0056b3
|
||||
transform: translateY(-2px)
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2)
|
||||
|
||||
&:active
|
||||
transform: translateY(0)
|
||||
|
||||
// Responsive Design
|
||||
@media (max-width: 480px)
|
||||
.main
|
||||
padding: var(--spacing-sm)
|
||||
|
||||
.header
|
||||
padding: var(--spacing-xs) var(--spacing-sm)
|
||||
|
||||
.header-content
|
||||
gap: var(--spacing-sm)
|
||||
|
||||
h1
|
||||
font-size: 1.25rem
|
||||
|
||||
.month-navigation
|
||||
.current-month
|
||||
font-size: 1rem
|
||||
min-width: 120px
|
||||
|
||||
.btn-icon
|
||||
width: 36px
|
||||
height: 36px
|
||||
|
||||
.view-controls
|
||||
flex-direction: column
|
||||
gap: var(--spacing-sm)
|
||||
align-items: stretch
|
||||
|
||||
.view-type-toggle
|
||||
justify-content: center
|
||||
|
||||
.user-select
|
||||
width: 100%
|
||||
|
||||
.day-header
|
||||
padding: var(--spacing-sm)
|
||||
|
||||
h3
|
||||
font-size: 1rem
|
||||
|
||||
.calendar-event
|
||||
padding: var(--spacing-sm)
|
||||
flex-direction: column
|
||||
align-items: stretch
|
||||
|
||||
.event-actions
|
||||
justify-content: flex-end
|
||||
margin-top: var(--spacing-sm)
|
||||
|
||||
.add-form-overlay
|
||||
padding: var(--spacing-sm)
|
||||
|
||||
.add-form
|
||||
padding: var(--spacing-md)
|
||||
max-height: 90vh
|
||||
|
||||
.fab-container
|
||||
bottom: var(--spacing-md)
|
||||
right: var(--spacing-md)
|
||||
|
||||
.fab
|
||||
width: 48px
|
||||
height: 48px
|
||||
font-size: 1.125rem
|
Reference in New Issue
Block a user